diff --git a/SourceAnalysisAndTool/jdkContainer/sourceAnalysis/heap.go b/SourceAnalysisAndTool/jdkContainer/sourceAnalysis/heap.go deleted file mode 100644 index 5783359..0000000 --- a/SourceAnalysisAndTool/jdkContainer/sourceAnalysis/heap.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package heap provides heap operations for any type that implements -// heap.Interface. A heap is a tree with the property that each node is the -// minimum-valued node in its subtree. -// -// The minimum element in the tree is the root, at index 0. -// -// A heap is a common way to implement a priority queue. To build a priority -// queue, implement the Heap interface with the (negative) priority as the -// ordering for the Less method, so Push adds items while Pop removes the -// highest-priority item from the queue. The Examples include such an -// implementation; the file example_pq_test.go has the complete source. -// -//read note 拷贝一个代码过来解析.感觉在go里面拷贝代码简单多了,依赖可以直接使用。我在这边使用read note(自定义todo标识)来标识我的解析. -package sourceAnalysis - -import "sort" - -// The Interface type describes the requirements -// for a type using the routines in this package. -// Any type that implements it may be used as a -// min-heap with the following invariants (established after -// Init has been called or if the data is empty or sorted): -// -// !h.Less(j, i) for 0 <= i < h.Len() and 2*i+1 <= j <= 2*i+2 and j < h.Len() -// -// Note that Push and Pop in this interface are for package heap's -// implementation to call. To add and remove things from the heap, -// use heap.Push and heap.Pop. -type Interface interface { - sort.Interface - Push(x interface{}) // add x as element Len() - Pop() interface{} // remove and return element Len() - 1. -} - -// Init establishes the heap invariants required by the other routines in this package. -// Init is idempotent with respect to the heap invariants -// and may be called whenever the heap invariants may have been invalidated. -// The complexity is O(n) where n = h.Len(). -//read note 对整个Interface 进行重构,时间复杂度是 O(n) -func Init(h Interface) { - // heapify - n := h.Len() - //read note 从最小父节点,到第0位的根节点,分别向下进行重构处理(之所以要用循环是因为一次向下的重构,只能对一条连续的分支进行重构,不彻底.) - for i := n/2 - 1; i >= 0; i-- { - down(h, i, n) - } -} - -// Push pushes the element x onto the heap. -// The complexity is O(log n) where n = h.Len(). -// read note 这个Push方法是往 Interface里面去新增一个元素.和我们继承的Push方法有差别.这边同时候做了重构操作. -// 一次Push的时间复杂度是 O(logN),一次Init的时间复杂度是O(N),按道理Push的元素越多,Init的效率越高 -func Push(h Interface, x interface{}) { - //read note 先把元素添加进去 - h.Push(x) - //read note 然后在从下往上进行重构处理,正常情况下Push都是把元素添加在最后一个位置,如果实现的方法,把Push添加到其他位置如果不进行Init,应该是会有问题. - up(h, h.Len()-1) -} - -// Pop removes and returns the minimum element (according to Less) from the heap. -// The complexity is O(log n) where n = h.Len(). -// Pop is equivalent to Remove(h, 0). -//read note 把最小的元素输出,需要注意的是真正的Pop必须是调用这个方法,而不是我们继承的那个方法. -// 时间复杂度是O(logN) -func Pop(h Interface) interface{} { - //read note 真正的Pop输出的是最小的元素,也就是最小堆的第0位置的元素 - // 所以这边的操作是把第0位的数组放到最后一位,然后从位置0开始,到N-1的位置,对所有元素进行down(父子节点比较交换)的操作 - n := h.Len() - 1 - h.Swap(0, n) - down(h, 0, n) - return h.Pop() -} - -// Remove removes and returns the element at index i from the heap. -// The complexity is O(log n) where n = h.Len(). -//read note 移除某个位置的元素,时间复杂度是 o(logn) -func Remove(h Interface, i int) interface{} { - //read note 判断移除的下标不等于最后一个元素位置,要特殊处理 - n := h.Len() - 1 - if n != i { - //read note 交换第i个元素和最后一个元素 - h.Swap(i, n) - //read note Fix的处理操作,这边只会处理到移除一个元素后的位置,也就是说被移除的那个元素(在最后的位置)不会参与重构数组的操作 - if !down(h, i, n) { - up(h, i) - } - } - //read note 调用Pop,把最后一个元素返回回去 - return h.Pop() -} - -// Fix re-establishes the heap ordering after the element at index i has changed its value. -// Changing the value of the element at index i and then calling Fix is equivalent to, -// but less expensive than, calling Remove(h, i) followed by a Push of the new value. -// The complexity is O(log n) where n = h.Len(). -//read note 当下标为i的元素发生改变,需要进行一次Fix的处理,时间复杂度是 o(logn) -func Fix(h Interface, i int) { - //read note 想从下标i的这个元素往下查找处理,如果往下没有交换元素,再往上进行处理. - if !down(h, i, h.Len()) { - up(h, i) - } -} - -//read note h: 对应的数组数据 -//read note j:子节点的下标 -//read note 方法作用 -func up(h Interface, j int) { - for { - //read note 拿到对应的父节点的下标 - i := (j - 1) / 2 // parent - //read note 找到最后一个父节点 || 父节点比子节点小,则跳出循环 - if i == j || !h.Less(j, i) { - break - } - //read note 否则就是父节点比子节点的值大,需要交换对应的元素,然后找到父节点的下标,再往上找其父节点的关系 - h.Swap(i, j) - j = i - } -} - -//read note h: 对应的数组数据 -//read note i0: 需要下发处理的坐标,这边也就是左右子节点的父节点下标. -//read note n: 数组对应的总长度 -//read note 方法作用:从父节点开始,循环向下判断对应的元素是否在对应的环境上 -func down(h Interface, i0, n int) bool { - //read note 把父节点的下标拿出来 - i := i0 - - //read note 循环的结束条件是: - for { - //read note 找到左边子节点下标 - j1 := 2*i + 1 - //read note 退出条件1:超过最大长度或者是负值(这个应该是针对传入就有问题的处理) - if j1 >= n || j1 < 0 { // j1 < 0 after int overflow - break - } - //read note 拿到左孩子和右孩子中比较小的那个元素(的下标) - j := j1 // left child - if j2 := j1 + 1; j2 < n && h.Less(j2, j1) { - j = j2 // = 2*i + 2 // right child - } - - //read note 判断父节点和子节点的大小关系,小的元素应该在父节点,所以如果子节点本身就比较小,直接退出循环,否则交换元素 - //read note 然后再把下标移动到被交换的这个元素上,计算被交换的这个元素和它的左右子节点的大小关系,进入下一个循环 - if !h.Less(j, i) { - break - } - h.Swap(i, j) - i = j - } - //read note 判断是否发生了交换操作 - return i > i0 -} diff --git a/SourceAnalysisAndTool/jdkContainer/sourceAnalysis/list.go b/SourceAnalysisAndTool/jdkContainer/sourceAnalysis/list.go deleted file mode 100644 index 8b65bf8..0000000 --- a/SourceAnalysisAndTool/jdkContainer/sourceAnalysis/list.go +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package list implements a doubly linked list. -// -// To iterate over a list (where l is a *List): -// for e := l.Front(); e != nil; e = e.Next() { -// // do something with e.Value -// } -// -package sourceAnalysis - -// Element is an element of a linked list. -//read note list中对应的元素,list相当是通过一个链表来链接所有的Element元素. -type Element struct { - // Next and previous pointers in the doubly-linked list of elements. - // To simplify the implementation, internally a list l is implemented - // as a ring, such that &l.root is both the next element of the last - // list element (l.Back()) and the previous element of the first list - // element (l.Front()). - //read note 指向下一个和前一个元素的指针.internally a list l is implemented as a ring:内部实现实际是一个环 - next, prev *Element - - // The list to which this element belongs. - //read note 链表头,这边是设置表头为哨兵的模式进行链表的处理的 - list *List - - // The value stored with this element. - //read note Element中实际的元素值 - Value interface{} -} - -// Next returns the next list element or nil. -func (e *Element) Next() *Element { - //read note 获取下一个元素,这边判断条件包含 list不为空,以及next不为链表头结点(哨兵). - if p := e.next; e.list != nil && p != &e.list.root { - return p - } - return nil -} - -// Prev returns the previous list element or nil. -func (e *Element) Prev() *Element { - //read note 与Next一样的道理,判断list不为空,以及pre不等于链表头结点 - if p := e.prev; e.list != nil && p != &e.list.root { - return p - } - return nil -} - -// List represents a doubly linked list. -// The zero value for List is an empty list ready to use. -//read note 设置哨兵的链表实现 -type List struct { - //read note 哨兵结点 - root Element // sentinel list element, only &root, root.prev, and root.next are used - //read note 链表长度 - len int // current list length excluding (this) sentinel element -} - -// Init initializes or clears list l. -func (l *List) Init() *List { - //read note 初始化的时候,链表的哨兵结点pre和next是互相指向的,这也可以作为判断链表是否为空的依据 - l.root.next = &l.root - l.root.prev = &l.root - l.len = 0 - return l -} - -// New returns an initialized list. -func New() *List { return new(List).Init() } - -// Len returns the number of elements of list l. -// The complexity is O(1). -func (l *List) Len() int { return l.len } - -// Front returns the first element of list l or nil if the list is empty. -// read note 返回第一个元素,如果链表不为空,则返回哨兵结点的next就是一个链表结点 -func (l *List) Front() *Element { - if l.len == 0 { - return nil - } - return l.root.next -} - -// Back returns the last element of list l or nil if the list is empty. -// read note 所以list是一个环,如果链表不为空,则最后一个元素可以通过哨兵的prev来获取到. -func (l *List) Back() *Element { - if l.len == 0 { - return nil - } - return l.root.prev -} - -// lazyInit lazily initializes a zero List value. -func (l *List) lazyInit() { - if l.root.next == nil { - l.Init() - } -} - -// insert inserts e after at, increments l.len, and returns e. -//read note 在某一个位置后面加入一个element,只需要设置一下长度,前后链表地址的指向即可。 -func (l *List) insert(e, at *Element) *Element { - n := at.next - at.next = e - e.prev = at - e.next = n - n.prev = e - e.list = l - l.len++ - return e -} - -// insertValue is a convenience wrapper for insert(&Element{Value: v}, at). -func (l *List) insertValue(v interface{}, at *Element) *Element { - return l.insert(&Element{Value: v}, at) -} - -// remove removes e from its list, decrements l.len, and returns e. -//read note 移除某个元素,返回该元素并设置不相关的属性为空,防止内存泄露. -func (l *List) remove(e *Element) *Element { - e.prev.next = e.next - e.next.prev = e.prev - e.next = nil // avoid memory leaks - e.prev = nil // avoid memory leaks - e.list = nil - l.len-- - return e -} - -// move moves e to next to at and returns e. -//read note 移动某个元素,本质上和插入某个元素有点类似.即移除对应节点后,再在对应的节点后面插入该元素 -func (l *List) move(e, at *Element) *Element { - if e == at { - return e - } - e.prev.next = e.next - e.next.prev = e.prev - - n := at.next - at.next = e - e.prev = at - e.next = n - n.prev = e - - return e -} - -// Remove removes e from l if e is an element of list l. -// It returns the element value e.Value. -// The element must not be nil. -func (l *List) Remove(e *Element) interface{} { - if e.list == l { - // if e.list == l, l must have been initialized when e was inserted - // in l or l == nil (e is a zero Element) and l.remove will crash - l.remove(e) - } - return e.Value -} - -// PushFront inserts a new element e with value v at the front of list l and returns e. -func (l *List) PushFront(v interface{}) *Element { - l.lazyInit() - return l.insertValue(v, &l.root) -} - -// PushBack inserts a new element e with value v at the back of list l and returns e. -func (l *List) PushBack(v interface{}) *Element { - l.lazyInit() - return l.insertValue(v, l.root.prev) -} - -// InsertBefore inserts a new element e with value v immediately before mark and returns e. -// If mark is not an element of l, the list is not modified. -// The mark must not be nil. -func (l *List) InsertBefore(v interface{}, mark *Element) *Element { - if mark.list != l { - return nil - } - // see comment in List.Remove about initialization of l - return l.insertValue(v, mark.prev) -} - -// InsertAfter inserts a new element e with value v immediately after mark and returns e. -// If mark is not an element of l, the list is not modified. -// The mark must not be nil. -func (l *List) InsertAfter(v interface{}, mark *Element) *Element { - if mark.list != l { - return nil - } - // see comment in List.Remove about initialization of l - return l.insertValue(v, mark) -} - -// MoveToFront moves element e to the front of list l. -// If e is not an element of l, the list is not modified. -// The element must not be nil. -func (l *List) MoveToFront(e *Element) { - if e.list != l || l.root.next == e { - return - } - // see comment in List.Remove about initialization of l - l.move(e, &l.root) -} - -// MoveToBack moves element e to the back of list l. -// If e is not an element of l, the list is not modified. -// The element must not be nil. -func (l *List) MoveToBack(e *Element) { - if e.list != l || l.root.prev == e { - return - } - // see comment in List.Remove about initialization of l - l.move(e, l.root.prev) -} - -// MoveBefore moves element e to its new position before mark. -// If e or mark is not an element of l, or e == mark, the list is not modified. -// The element and mark must not be nil. -func (l *List) MoveBefore(e, mark *Element) { - if e.list != l || e == mark || mark.list != l { - return - } - l.move(e, mark.prev) -} - -// MoveAfter moves element e to its new position after mark. -// If e or mark is not an element of l, or e == mark, the list is not modified. -// The element and mark must not be nil. -func (l *List) MoveAfter(e, mark *Element) { - if e.list != l || e == mark || mark.list != l { - return - } - l.move(e, mark) -} - -// PushBackList inserts a copy of an other list at the back of list l. -// The lists l and other may be the same. They must not be nil. -func (l *List) PushBackList(other *List) { - l.lazyInit() - for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { - l.insertValue(e.Value, l.root.prev) - } -} - -// PushFrontList inserts a copy of an other list at the front of list l. -// The lists l and other may be the same. They must not be nil. -func (l *List) PushFrontList(other *List) { - l.lazyInit() - for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { - l.insertValue(e.Value, &l.root) - } -} diff --git a/SourceAnalysisAndTool/jdkContainer/sourceAnalysis/ring.go b/SourceAnalysisAndTool/jdkContainer/sourceAnalysis/ring.go deleted file mode 100644 index 063a361..0000000 --- a/SourceAnalysisAndTool/jdkContainer/sourceAnalysis/ring.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package ring implements operations on circular lists. -package sourceAnalysis - -// A Ring is an element of a circular list, or ring. -// Rings do not have a beginning or end; a pointer to any ring element -// serves as reference to the entire ring. Empty rings are represented -// as nil Ring pointers. The zero value for a Ring is a one-element -// ring with a nil Value. -// -//read note 环结构:指针可能指向任意元素,空链表只有一个nil元素 -type Ring struct { - next, prev *Ring - Value interface{} // for use by client; untouched by this library -} - -//read note 初始化只是做了指针指向,不会增加环的值 -func (r *Ring) init() *Ring { - r.next = r - r.prev = r - return r -} - -// Next returns the next ring element. r must not be empty. -//read note:环的下一个值,如果环的next为空,则初始化该环 -func (r *Ring) Next() *Ring { - if r.next == nil { - return r.init() - } - return r.next -} - -// Prev returns the previous ring element. r must not be empty. -func (r *Ring) Prev() *Ring { - if r.next == nil { - return r.init() - } - return r.prev -} - -// Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0) -// in the ring and returns that ring element. r must not be empty. -// -//read note 对环上的当前元素进行n次位置的移动,小于0则向后移动,大于0则向前移动 -func (r *Ring) Move(n int) *Ring { - if r.next == nil { - return r.init() - } - switch { - case n < 0: - for ; n < 0; n++ { - r = r.prev - } - case n > 0: - for ; n > 0; n-- { - r = r.next - } - } - return r -} - -// New creates a ring of n elements. -//read note 创建n个节点的环 -func New1(n int) *Ring { - if n <= 0 { - return nil - } - r := new(Ring) - p := r - for i := 1; i < n; i++ { - p.next = &Ring{prev: p} - p = p.next - } - p.next = r - r.prev = p - return r -} - -// Link connects ring r with ring s such that r.Next() -// becomes s and returns the original value for r.Next(). -// r must not be empty. -// -// If r and s point to the same ring, linking -// them removes the elements between r and s from the ring. -// The removed elements form a subring and the result is a -// reference to that subring (if no elements were removed, -// the result is still the original value for r.Next(), -// and not nil). -// -// If r and s point to different rings, linking -// them creates a single ring with the elements of s inserted -// after r. The result points to the element following the -// last element of s after insertion. -// -//read note 链接环,如果是两个相同的环则环不改变,链接完环会少掉原来的第一个元素....(神奇) -// 如果是两个不同的环,则把另一个环接到上一个环的后面,链接完的第一个元素是原来环的next的元素.第二个元素 -func (r *Ring) Link(s *Ring) *Ring { - n := r.Next() - if s != nil { - p := s.Prev() - // Note: Cannot use multiple assignment because - // evaluation order of LHS is not specified. - r.next = s - s.prev = r - n.prev = p - p.next = n - } - return n -} - -// Unlink removes n % r.Len() elements from the ring r, starting -// at r.Next(). If n % r.Len() == 0, r remains unchanged. -// The result is the removed subring. r must not be empty. -// -//read note 断开环上n个元素,这里会根据n%r.Len 得到的余数进行Unlink,因为环是没有起点终点的,所以超过或者不超过环的长度都是按照余数进行处理 -func (r *Ring) Unlink(n int) *Ring { - if n <= 0 { - return nil - } - return r.Link(r.Move(n + 1)) -} - -// Len computes the number of elements in ring r. -// It executes in time proportional to the number of elements. -// -func (r *Ring) Len() int { - n := 0 - if r != nil { - n = 1 - for p := r.Next(); p != r; p = p.next { - n++ - } - } - return n -} - -// Do calls function f on each element of the ring, in forward order. -// The behavior of Do is undefined if f changes *r. -//read note 对环上的所有元素进行函数操作,但是这边的操作好像是没办法改变环中的元素的,只能进行提取或者输出 -func (r *Ring) Do(f func(interface{})) { - if r != nil { - f(r.Value) - for p := r.Next(); p != r; p = p.next { - f(p.Value) - } - } -} diff --git a/SourceAnalysisAndTool/jdkContainer/testContainer/HeapTool.go b/SourceAnalysisAndTool/jdkContainer/testContainer/HeapTool.go deleted file mode 100644 index 7fe4549..0000000 --- a/SourceAnalysisAndTool/jdkContainer/testContainer/HeapTool.go +++ /dev/null @@ -1,36 +0,0 @@ -/* - * @Author : huangzj - * @Time : 2020/12/2 15:39 - * @Description: - */ - -package testContainer - -type Person struct { - Name string //名字 - Age int //年龄 - Money float64 //身价 -} - -type heapTool []*Person - -func (h *heapTool) Less(i, j int) bool { - return (*h)[i].Age < (*h)[j].Age -} - -func (h *heapTool) Swap(i, j int) { - (*h)[i], (*h)[j] = (*h)[j], (*h)[i] -} - -func (h *heapTool) Len() int { - return len(*h) -} - -func (h *heapTool) Pop() (v interface{}) { - *h, v = (*h)[:h.Len()-1], (*h)[h.Len()-1] - return -} - -func (h *heapTool) Push(v interface{}) { - *h = append(*h, v.(*Person)) -} diff --git a/SourceAnalysisAndTool/jdkContainer/testContainer/heap_test.go b/SourceAnalysisAndTool/jdkContainer/testContainer/heap_test.go deleted file mode 100644 index 83d3ee9..0000000 --- a/SourceAnalysisAndTool/jdkContainer/testContainer/heap_test.go +++ /dev/null @@ -1,62 +0,0 @@ -/* - * @Author : huangzj - * @Time : 2020/12/2 11:19 - * @Description: - */ - -package testContainer - -import ( - "container/heap" - "fmt" - "testing" -) - -func TestHeapTool(t *testing.T) { - personList := new(heapTool) - personList.Push(&Person{ - Name: "小明", - Age: 20, - Money: 100000.99, - }) - personList.Push(&Person{ - Name: "小施", - Age: 30, - Money: 1002341.99, - }) - - personList.Push(&Person{ - Name: "小康", - Age: 10, - Money: 200.99, - }) - - personList.Push(&Person{ - Name: "老施", - Age: 50, - Money: 10343240000.99, - }) - - personList.Push(&Person{ - Name: "老康", - Age: 70, - Money: 10340.99, - }) - personList.Push(&Person{ - Name: "老明", - Age: 80, - Money: 13240000.99, - }) - personList.Push(&Person{ - Name: "老林", - Age: 90, - Money: 10340000.99, - }) - - heap.Init(personList) - for personList.Len() > 0 { - pop := heap.Pop(personList) - fmt.Println(fmt.Sprintf("%v,%v岁,资产:%v", pop.(*Person).Name, pop.(*Person).Age, pop.(*Person).Money)) - } - -} diff --git a/SourceAnalysisAndTool/jdkContainer/testContainer/list_test.go b/SourceAnalysisAndTool/jdkContainer/testContainer/list_test.go deleted file mode 100644 index 7f2f4f2..0000000 --- a/SourceAnalysisAndTool/jdkContainer/testContainer/list_test.go +++ /dev/null @@ -1,69 +0,0 @@ -/* - * @Author : huangzj - * @Time : 2020/12/3 21:58 - * @Description:测试list.go包的元素 - */ - -package testContainer - -import ( - "container/list" - "fmt" - "testing" -) - -func TestList(t *testing.T) { - list2 := list.New() - - list2.PushFront(Person{ - Name: "康康", - Age: 10, - Money: 20, - }) - - list2.PushBack(Person{ - Name: "老施", - Age: 40, - Money: 1000000, - }) - for e := list2.Front(); e != nil; e = e.Next() { - value := e.Value.(Person) - fmt.Println(fmt.Sprintf("名字:%v,年龄:%v,身家:%v", value.Name, value.Age, value.Money)) - } - fmt.Println() - fmt.Println() - - frontE := list2.Front() - list2.MoveToBack(frontE) - - for e := list2.Front(); e != nil; e = e.Next() { - value := e.Value.(Person) - fmt.Println(fmt.Sprintf("名字:%v,年龄:%v,身家:%v", value.Name, value.Age, value.Money)) - } - fmt.Println() - fmt.Println() - - xiaozhang := list2.InsertBefore(Person{ - Name: "小张", - Age: 10, - Money: 50, - }, list2.Front()) - for e := list2.Front(); e != nil; e = e.Next() { - value := e.Value.(Person) - fmt.Println(fmt.Sprintf("名字:%v,年龄:%v,身家:%v", value.Name, value.Age, value.Money)) - } - fmt.Println() - fmt.Println() - - list2.Remove(xiaozhang) - for e := list2.Front(); e != nil; e = e.Next() { - value := e.Value.(Person) - fmt.Println(fmt.Sprintf("名字:%v,年龄:%v,身家:%v", value.Name, value.Age, value.Money)) - } - fmt.Println() - fmt.Println() - - front := list2.Front().Value.(Person) - fmt.Println(fmt.Sprintf("名字:%v,年龄:%v,身家:%v", front.Name, front.Age, front.Money)) - -} diff --git a/SourceAnalysisAndTool/jdkContainer/testContainer/ring_test.go b/SourceAnalysisAndTool/jdkContainer/testContainer/ring_test.go deleted file mode 100644 index 14888a3..0000000 --- a/SourceAnalysisAndTool/jdkContainer/testContainer/ring_test.go +++ /dev/null @@ -1,114 +0,0 @@ -/* - * @Author : huangzj - * @Time : 2020/12/7 9:33 - * @Description: - */ - -package testContainer - -import ( - "container/ring" - "fmt" - "testing" -) - -func TestRing(t *testing.T) { - fmt.Println("测试空链表") - var rings ring.Ring - fmt.Println(rings.Next().Value) - - fmt.Println("") - fmt.Println("") - - fmt.Println("测试环") - newRing := makeN(10) - Print(newRing) - - fmt.Println("") - fmt.Println("") - fmt.Println("测试环Link自己") - newRing = makeN(10) - newRing = newRing.Link(newRing) - Print(newRing) - - fmt.Println() - fmt.Println() - fmt.Println("测试环Link其他环") - newRing = makeN(10) - newRing1 := makeN(5) - newRing = newRing.Link(newRing1) - Print(newRing) - - fmt.Println() - fmt.Println() - fmt.Println("测试Move") - newRing1 = makeN(5) - newRing1 = newRing1.Move(3) - Print(newRing1) - - fmt.Println() - fmt.Println() - fmt.Println("测试Do,没有办法改变环中的元素.") - newRing1 = makeN(5) - newRing1.Do(func(i interface{}) { - i = i.(int) + 1000 - }) - Print(newRing1) - - newRingx := ring.New(3) - for i := 1; i <= newRingx.Len(); i++ { - newRingx.Value = Person{ - Name: "小明", - Age: 100, - Money: 19999, - } - newRingx = newRingx.Next() - newRingx.Value = Person{ - Name: "小康", - Age: 50, - Money: 19921999, - } - newRingx = newRingx.Next() - newRingx.Value = Person{ - Name: "小施", - Age: 20, - Money: 1111999, - } - } - fmt.Println("测试Do,只能对元素进行提取或者输出.") - s := make([]int, 0) - newRingx.Do(func(i interface{}) { - s = append(s, i.(Person).Age) - }) - for _, item := range s { - fmt.Println(item) - } - - fmt.Println() - fmt.Println() - fmt.Println("测试Unlink") - newRing1 = makeN(5) - newRing2 := newRing1.Unlink(2) - Print(newRing1) - println() - fmt.Println("如果用赋值语句,可以返回被移除的元素") - Print(newRing2) -} - -func Print(r *ring.Ring) { - i, n := 0, r.Len() - for p := r; i < n; p = p.Next() { - fmt.Println(fmt.Sprintf("当前元素是%v", p.Value)) - i++ - } -} - -//创造对应的链表 -func makeN(n int) *ring.Ring { - r := ring.New(n) - for i := 1; i <= n; i++ { - r.Value = i - r = r.Next() - } - return r -} diff --git a/SourceAnalysisAndTool/validator.v8/2、结构体缓存获取.jpg b/SourceAnalysisAndTool/validator.v8/2、结构体缓存获取.jpg deleted file mode 100644 index 8eadd1a..0000000 Binary files a/SourceAnalysisAndTool/validator.v8/2、结构体缓存获取.jpg and /dev/null differ diff --git a/SourceAnalysisAndTool/validator.v8/readme.md b/SourceAnalysisAndTool/validator.v8/readme.md deleted file mode 100644 index 29bb391..0000000 --- a/SourceAnalysisAndTool/validator.v8/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -我的分析文章可参考:[Go源码解析:validator.v8](https://blog.csdn.net/qq_34326321/article/details/111030128) - -流程图: ![image](2、结构体缓存获取.jpg) - -流程图地址:[地址](https://www.processon.com/view/link/5fd6dabb63768906e6db0d25) \ No newline at end of file diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/.gitignore b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/.gitignore deleted file mode 100644 index 792ca00..0000000 --- a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof -*.test -*.out -*.txt -cover.html -README.html \ No newline at end of file diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/LICENSE b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/LICENSE deleted file mode 100644 index 6a2ae9a..0000000 --- a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Dean Karn - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/README.md b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/README.md deleted file mode 100644 index d3bd9b0..0000000 --- a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/README.md +++ /dev/null @@ -1,366 +0,0 @@ -Package validator -================ -[![Join the chat at https://gitter.im/bluesuncorp/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -![Project status](https://img.shields.io/badge/version-8.18.2-green.svg) -[![Build Status](https://semaphoreci.com/api/v1/projects/ec20115f-ef1b-4c7d-9393-cc76aba74eb4/530054/badge.svg)](https://semaphoreci.com/joeybloggs/validator) -[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=v8&service=github)](https://coveralls.io/github/go-playground/validator?branch=v8) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) -[![GoDoc](https://godoc.org/gopkg.in/go-playground/validator.v8?status.svg)](https://godoc.org/gopkg.in/go-playground/validator.v8) -![License](https://img.shields.io/dub/l/vibe-d.svg) - -Package validator implements value validations for structs and individual fields based on tags. - -It has the following **unique** features: - -- Cross Field and Cross Struct validations by using validation tags or custom validators. -- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated. -- Handles type interface by determining it's underlying type prior to validation. -- Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29) -- Alias validation tags, which allows for mapping of several validations to a single tag for easier defining of validations on structs -- Extraction of custom defined Field Name e.g. can specify to extract the JSON name while validating and have it available in the resulting FieldError - -Installation ------------- - -Use go get. - - go get gopkg.in/go-playground/validator.v8 - -or to update - - go get -u gopkg.in/go-playground/validator.v8 - -Then import the validator package into your own code. - - import "gopkg.in/go-playground/validator.v8" - -Error Return Value -------- - -Validation functions return type error - -They return type error to avoid the issue discussed in the following, where err is always != nil: - -* http://stackoverflow.com/a/29138676/3158232 -* https://github.com/go-playground/validator/issues/134 - -validator only returns nil or ValidationErrors as type error; so in you code all you need to do -is check if the error returned is not nil, and if it's not type cast it to type ValidationErrors -like so: - -```go -err := validate.Struct(mystruct) -validationErrors := err.(validator.ValidationErrors) - ``` - -Usage and documentation ------- - -Please see http://godoc.org/gopkg.in/go-playground/validator.v8 for detailed usage docs. - -##### Examples: - -Struct & Field validation -```go -package main - -import ( - "fmt" - - "gopkg.in/go-playground/validator.v8" -) - -// User contains user information -type User struct { - FirstName string `validate:"required"` - LastName string `validate:"required"` - Age uint8 `validate:"gte=0,lte=130"` - Email string `validate:"required,email"` - FavouriteColor string `validate:"hexcolor|rgb|rgba"` - Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage... -} - -// Address houses a users address information -type Address struct { - Street string `validate:"required"` - City string `validate:"required"` - Planet string `validate:"required"` - Phone string `validate:"required"` -} - -var validate *validator.Validate - -func main() { - - config := &validator.Config{TagName: "validate"} - - validate = validator.New(config) - - validateStruct() - validateField() -} - -func validateStruct() { - - address := &Address{ - Street: "Eavesdown Docks", - Planet: "Persphone", - Phone: "none", - } - - user := &User{ - FirstName: "Badger", - LastName: "Smith", - Age: 135, - Email: "Badger.Smith@gmail.com", - FavouriteColor: "#000", - Addresses: []*Address{address}, - } - - // returns nil or ValidationErrors ( map[string]*FieldError ) - errs := validate.Struct(user) - - if errs != nil { - - fmt.Println(errs) // output: Key: "User.Age" Error:Field validation for "Age" failed on the "lte" tag - // Key: "User.Addresses[0].City" Error:Field validation for "City" failed on the "required" tag - err := errs.(validator.ValidationErrors)["User.Addresses[0].City"] - fmt.Println(err.Field) // output: City - fmt.Println(err.Tag) // output: required - fmt.Println(err.Kind) // output: string - fmt.Println(err.Type) // output: string - fmt.Println(err.Param) // output: - fmt.Println(err.Value) // output: - - // from here you can create your own error messages in whatever language you wish - return - } - - // save user to database -} - -func validateField() { - myEmail := "joeybloggs.gmail.com" - - errs := validate.Field(myEmail, "required,email") - - if errs != nil { - fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag - return - } - - // email ok, move on -} -``` - -Custom Field Type -```go -package main - -import ( - "database/sql" - "database/sql/driver" - "fmt" - "reflect" - - "gopkg.in/go-playground/validator.v8" -) - -// DbBackedUser User struct -type DbBackedUser struct { - Name sql.NullString `validate:"required"` - Age sql.NullInt64 `validate:"required"` -} - -func main() { - - config := &validator.Config{TagName: "validate"} - - validate := validator.New(config) - - // register all sql.Null* types to use the ValidateValuer CustomTypeFunc - validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{}) - - x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}} - errs := validate.Struct(x) - - if len(errs.(validator.ValidationErrors)) > 0 { - fmt.Printf("Errs:\n%+v\n", errs) - } -} - -// ValidateValuer implements validator.CustomTypeFunc -func ValidateValuer(field reflect.Value) interface{} { - if valuer, ok := field.Interface().(driver.Valuer); ok { - val, err := valuer.Value() - if err == nil { - return val - } - // handle the error how you want - } - return nil -} -``` - -Struct Level Validation -```go -package main - -import ( - "fmt" - "reflect" - - "gopkg.in/go-playground/validator.v8" -) - -// User contains user information -type User struct { - FirstName string `json:"fname"` - LastName string `json:"lname"` - Age uint8 `validate:"gte=0,lte=130"` - Email string `validate:"required,email"` - FavouriteColor string `validate:"hexcolor|rgb|rgba"` - Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage... -} - -// Address houses a users address information -type Address struct { - Street string `validate:"required"` - City string `validate:"required"` - Planet string `validate:"required"` - Phone string `validate:"required"` -} - -var validate *validator.Validate - -func main() { - - config := &validator.Config{TagName: "validate"} - - validate = validator.New(config) - validate.RegisterStructValidation(UserStructLevelValidation, User{}) - - validateStruct() -} - -// UserStructLevelValidation contains custom struct level validations that don't always -// make sense at the field validation level. For Example this function validates that either -// FirstName or LastName exist; could have done that with a custom field validation but then -// would have had to add it to both fields duplicating the logic + overhead, this way it's -// only validated once. -// -// NOTE: you may ask why wouldn't I just do this outside of validator, because doing this way -// hooks right into validator and you can combine with validation tags and still have a -// common error output format. -func UserStructLevelValidation(v *validator.Validate, structLevel *validator.StructLevel) { - - user := structLevel.CurrentStruct.Interface().(User) - - if len(user.FirstName) == 0 && len(user.LastName) == 0 { - structLevel.ReportError(reflect.ValueOf(user.FirstName), "FirstName", "fname", "fnameorlname") - structLevel.ReportError(reflect.ValueOf(user.LastName), "LastName", "lname", "fnameorlname") - } - - // plus can to more, even with different tag than "fnameorlname" -} - -func validateStruct() { - - address := &Address{ - Street: "Eavesdown Docks", - Planet: "Persphone", - Phone: "none", - City: "Unknown", - } - - user := &User{ - FirstName: "", - LastName: "", - Age: 45, - Email: "Badger.Smith@gmail.com", - FavouriteColor: "#000", - Addresses: []*Address{address}, - } - - // returns nil or ValidationErrors ( map[string]*FieldError ) - errs := validate.Struct(user) - - if errs != nil { - - fmt.Println(errs) // output: Key: 'User.LastName' Error:Field validation for 'LastName' failed on the 'fnameorlname' tag - // Key: 'User.FirstName' Error:Field validation for 'FirstName' failed on the 'fnameorlname' tag - err := errs.(validator.ValidationErrors)["User.FirstName"] - fmt.Println(err.Field) // output: FirstName - fmt.Println(err.Tag) // output: fnameorlname - fmt.Println(err.Kind) // output: string - fmt.Println(err.Type) // output: string - fmt.Println(err.Param) // output: - fmt.Println(err.Value) // output: - - // from here you can create your own error messages in whatever language you wish - return - } - - // save user to database -} -``` - -Benchmarks ------- -###### Run on MacBook Pro (Retina, 15-inch, Late 2013) 2.6 GHz Intel Core i7 16 GB 1600 MHz DDR3 using Go version go1.5.3 darwin/amd64 -```go -PASS -BenchmarkFieldSuccess-8 20000000 118 ns/op 0 B/op 0 allocs/op -BenchmarkFieldFailure-8 2000000 758 ns/op 432 B/op 4 allocs/op -BenchmarkFieldDiveSuccess-8 500000 2471 ns/op 464 B/op 28 allocs/op -BenchmarkFieldDiveFailure-8 500000 3172 ns/op 896 B/op 32 allocs/op -BenchmarkFieldCustomTypeSuccess-8 5000000 300 ns/op 32 B/op 2 allocs/op -BenchmarkFieldCustomTypeFailure-8 2000000 775 ns/op 432 B/op 4 allocs/op -BenchmarkFieldOrTagSuccess-8 1000000 1122 ns/op 4 B/op 1 allocs/op -BenchmarkFieldOrTagFailure-8 1000000 1167 ns/op 448 B/op 6 allocs/op -BenchmarkStructLevelValidationSuccess-8 3000000 548 ns/op 160 B/op 5 allocs/op -BenchmarkStructLevelValidationFailure-8 3000000 558 ns/op 160 B/op 5 allocs/op -BenchmarkStructSimpleCustomTypeSuccess-8 2000000 623 ns/op 36 B/op 3 allocs/op -BenchmarkStructSimpleCustomTypeFailure-8 1000000 1381 ns/op 640 B/op 9 allocs/op -BenchmarkStructPartialSuccess-8 1000000 1036 ns/op 272 B/op 9 allocs/op -BenchmarkStructPartialFailure-8 1000000 1734 ns/op 730 B/op 14 allocs/op -BenchmarkStructExceptSuccess-8 2000000 888 ns/op 250 B/op 7 allocs/op -BenchmarkStructExceptFailure-8 1000000 1036 ns/op 272 B/op 9 allocs/op -BenchmarkStructSimpleCrossFieldSuccess-8 2000000 773 ns/op 80 B/op 4 allocs/op -BenchmarkStructSimpleCrossFieldFailure-8 1000000 1487 ns/op 536 B/op 9 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 1000000 1261 ns/op 112 B/op 7 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldFailure-8 1000000 2055 ns/op 576 B/op 12 allocs/op -BenchmarkStructSimpleSuccess-8 3000000 519 ns/op 4 B/op 1 allocs/op -BenchmarkStructSimpleFailure-8 1000000 1429 ns/op 640 B/op 9 allocs/op -BenchmarkStructSimpleSuccessParallel-8 10000000 146 ns/op 4 B/op 1 allocs/op -BenchmarkStructSimpleFailureParallel-8 2000000 551 ns/op 640 B/op 9 allocs/op -BenchmarkStructComplexSuccess-8 500000 3269 ns/op 244 B/op 15 allocs/op -BenchmarkStructComplexFailure-8 200000 8436 ns/op 3609 B/op 60 allocs/op -BenchmarkStructComplexSuccessParallel-8 1000000 1024 ns/op 244 B/op 15 allocs/op -BenchmarkStructComplexFailureParallel-8 500000 3536 ns/op 3609 B/op 60 allocs/op -``` - -Complimentary Software ----------------------- - -Here is a list of software that compliments using this library either pre or post validation. - -* [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support. -* [Conform](https://github.com/leebenson/conform) - Trims, sanitizes & scrubs data based on struct tags. - -How to Contribute ------- - -There will always be a development branch for each version i.e. `v1-development`. In order to contribute, -please make your pull requests against those branches. - -If the changes being proposed or requested are breaking changes, please create an issue, for discussion -or create a pull request against the highest development branch for example this package has a -v1 and v1-development branch however, there will also be a v2-development branch even though v2 doesn't exist yet. - -I strongly encourage everyone whom creates a custom validation function to contribute them and -help make this package even better. - -License ------- -Distributed under MIT License, please see license file in code for more details. diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/baked_in.go b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/baked_in.go deleted file mode 100644 index 558616e..0000000 --- a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/baked_in.go +++ /dev/null @@ -1,1429 +0,0 @@ -package validator - -import ( - "fmt" - "net" - "net/url" - "reflect" - "strings" - "time" - "unicode/utf8" -) - -// BakedInAliasValidators is a default mapping of a single validationstag that -// defines a common or complex set of validation(s) to simplify -// adding validation to structs. i.e. set key "_ageok" and the tags -// are "gt=0,lte=130" or key "_preferredname" and tags "omitempty,gt=0,lte=60" -//read note 别名标签,通过别名定义规则,默认是iscolor -// 它的作用比较神奇,就是说通过iscolor这个标签就可以判断后面一组的规则 -// 比如说这边 iscolor对应的是 hexcolor|rgb|rgba|hsl|hsla -// 如果我在tag中使用iscolor标签,则validator会去校验 是否满足 hexcolor | 是否满足 rgb | 是否满足 rgba | 是否满足 hsl | 是否满足 hsla (|:或者) -var bakedInAliasValidators = map[string]string{ - "iscolor": "hexcolor|rgb|rgba|hsl|hsla", -} - -// BakedInValidators is the default map of ValidationFunc -// you can add, remove or even replace items to suite your needs, -// or even disregard and use your own map if so desired. -//read note 默认的校验映射map. key是tag标签,value是对应tag标签的处理类 -// 具体校验实现可参考:https://blog.csdn.net/weixin_30896511/article/details/98428064 -var bakedInValidators = map[string]Func{ - "required": HasValue, //read note 参数需要有值 - "len": HasLengthOf, //read note 数值类型判断的是值相等, Map Slice Array判断的是长度相等,string判断的是Rune数组长度相等 - "min": HasMinOf, //read note 数值类型判断的是值【大于等于】min, Map Slice Array判断的是长度【大于等于】min,string判断的是Rune数组长度【大于等于】min - "max": HasMaxOf, //read note 数值类型判断的是值【小于等于】max, Map Slice Array判断的是长度【小于等于】max,string判断的是Rune数组长度【小于等于】max - "eq": IsEq, //read note 字符串或者数值类型,判断的是值【相等】,Map Slice Array判断长度是否【相等】 - "ne": IsNe, //read note 字符串或者数值类型,判断的是值【不相等】,Map Slice Array判断长度是否【不相等】 - "lt": IsLt, //read note 数值类型判断的是值【小于】lt, Map Slice Array判断的是长度【小于】lt,string判断的是Rune数组长度【小于】lt - "lte": IsLte, //类似max的操作,但是这边多了一步处理就是判断如果是【time.Time】,比较时间在当前时间之前或者等于当前时间 - "gt": IsGt, //read note 数值类型判断的是值【大于】gt, Map Slice Array判断的是长度【大于】gt,string判断的是Rune数组长度【大于】gt - "gte": IsGte, //类似min的操作,但是这边多了一步处理就是判断如果是【time.Time】,比较时间在当前时间之后或者等于当前时间 - - //read note 判断关联字段(标签标识关联字段的名字)和当前字段的值的关系,数值是判断值相等,Map Slice Array判断长度,如果有time.Time判断时间和当前时间前后关系,否则判断reflect.String - "eqfield": IsEqField, - "eqcsfield": IsEqCrossStructField, - "necsfield": IsNeCrossStructField, - "gtcsfield": IsGtCrossStructField, - "gtecsfield": IsGteCrossStructField, - "ltcsfield": IsLtCrossStructField, - "ltecsfield": IsLteCrossStructField, - "nefield": IsNeField, - "gtefield": IsGteField, - "gtfield": IsGtField, - "ltefield": IsLteField, - "ltfield": IsLtField, - - "alpha": IsAlpha, //这将验证字符串值是否仅包含ASCII字母字符 - "alphanum": IsAlphanum, //这将验证字符串值是否仅包含ASCII字母数字字符 - - "numeric": IsNumeric, //这将验证字符串值是否包含基本数值。基本排除指数等...对于整数或浮点数,它返回true。 - "number": IsNumber, //判断是否Number - "hexadecimal": IsHexadecimal, //这将验证字符串值是否包含有效的十六进制 - - "hexcolor": IsHEXColor, //这验证字符串值包含有效的十六进制颜色,包括#标签(#) - "rgb": IsRGB, //这将验证字符串值是否包含有效的rgb颜色 - "rgba": IsRGBA, //这将验证字符串值是否包含有效的rgba颜色 - "hsl": IsHSL, //这将验证字符串值是否包含有效的hsl颜色 - "hsla": IsHSLA, //这将验证字符串值是否包含有效的hsla颜色 - - "email": IsEmail, //这验证字符串值包含有效的电子邮件这可能不符合任何rfc标准的所有可能性,但任何电子邮件提供商都不接受所有可能性 - "url": IsURL, //这会验证字符串值是否包含有效的url这将接受golang请求uri接受的任何url,但必须包含一个模式,例如http://或rtmp:// - "uri": IsURI, //这验证了字符串值包含有效的uri。这将接受uri接受的golang请求的任何uri - "base64": IsBase64, //这将验证字符串值是否包含有效的base64值。虽然空字符串是有效的base64,但这会将空字符串报告为错误,如果您希望接受空字符串作为有效字符,则可以将此字符串与omitempty标记一起使用。 - - //read note 验证字符串是否【包含】/【不包含】对应的子字符串(这个方法看源码是处理Field.String()是否包含对应的子串,而如果不是字符串的话返回的是,不知道这个会不会被对比) - "contains": Contains, - "containsany": ContainsAny, - "containsrune": ContainsRune, - "excludes": Excludes, - "excludesall": ExcludesAll, - "excludesrune": ExcludesRune, - - //read note 校验字符串是否有效的isbn值 - "isbn": IsISBN, - "isbn10": IsISBN10, - "isbn13": IsISBN13, - - //read note 校验字符串是否有效的uuid值 - "uuid": IsUUID, - "uuid3": IsUUID3, - "uuid4": IsUUID4, - "uuid5": IsUUID5, - - "ascii": IsASCII, //这将验证字符串值是否仅包含ASCII字符。注意:如果字符串为空,则验证为true - "printascii": IsPrintableASCII, //这将验证字符串值是否仅包含可打印的ASCII字符。注意:如果字符串为空,则验证为true。 - "multibyte": HasMultiByteCharacter, //这将验证字符串值是否包含一个或多个多字节字符。注意:如果字符串为空,则验证为true - "datauri": IsDataURI, //这将验证字符串值是否包含有效的DataURI。注意:这也将验证数据部分是否有效base64 - "latitude": IsLatitude, //这将验证字符串值是否包含有效的纬度。 - "longitude": IsLongitude, //这将验证字符串值是否包含有效经度。 - "ssn": IsSSN, //这将验证字符串值是否包含有效的美国社会安全号码。 - "ipv4": IsIPv4, //这将验证字符串值是否包含有效的v4 IP地址 - "ipv6": IsIPv6, //这将验证字符串值是否包含有效的v6 IP地址 - "ip": IsIP, //这将验证字符串值是否包含有效的IP地址 - "cidrv4": IsCIDRv4, //这将验证字符串值是否包含有效的v4 CIDR地址 - "cidrv6": IsCIDRv6, //这将验证字符串值是否包含有效的v6 CIDR地址 - "cidr": IsCIDR, //这将验证字符串值是否包含有效的CIDR地址 - "tcp4_addr": IsTCP4AddrResolvable, //这将验证字符串值是否包含有效的可解析v4 TCP地址 - "tcp6_addr": IsTCP6AddrResolvable, //这将验证字符串值是否包含有效的可解析v6 TCP地址 - "tcp_addr": IsTCPAddrResolvable, //这将验证字符串值是否包含有效的可解析TCP地址 - "udp4_addr": IsUDP4AddrResolvable, //这将验证字符串值是否包含有效的可解析v4 UDP地址 - "udp6_addr": IsUDP6AddrResolvable, //这将验证字符串值是否包含有效的可解析v6 UDP地址 - "udp_addr": IsUDPAddrResolvable, //这将验证字符串值是否包含有效的可解析UDP地址 - "ip4_addr": IsIP4AddrResolvable, //这将验证字符串值是否包含有效的可解析v4 IP地址 - "ip6_addr": IsIP6AddrResolvable, //这将验证字符串值是否包含有效的可解析v6 IP地址 - "ip_addr": IsIPAddrResolvable, //这将验证字符串值是否包含有效的可解析IP地址 - "unix_addr": IsUnixAddrResolvable, //这将验证字符串值是否包含有效的Unix地址 - "mac": IsMAC, //这将验证字符串值是否包含有效的MAC地址 -} - -// IsMAC is the validation function for validating if the field's value is a valid MAC address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsMAC(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - _, err := net.ParseMAC(field.String()) - return err == nil -} - -// IsCIDRv4 is the validation function for validating if the field's value is a valid v4 CIDR address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsCIDRv4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - ip, _, err := net.ParseCIDR(field.String()) - - return err == nil && ip.To4() != nil -} - -// IsCIDRv6 is the validation function for validating if the field's value is a valid v6 CIDR address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsCIDRv6(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - ip, _, err := net.ParseCIDR(field.String()) - - return err == nil && ip.To4() == nil -} - -// IsCIDR is the validation function for validating if the field's value is a valid v4 or v6 CIDR address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsCIDR(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - _, _, err := net.ParseCIDR(field.String()) - - return err == nil -} - -// IsIPv4 is the validation function for validating if a value is a valid v4 IP address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsIPv4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - ip := net.ParseIP(field.String()) - - return ip != nil && ip.To4() != nil -} - -// IsIPv6 is the validation function for validating if the field's value is a valid v6 IP address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsIPv6(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - ip := net.ParseIP(field.String()) - - return ip != nil && ip.To4() == nil -} - -// IsIP is the validation function for validating if the field's value is a valid v4 or v6 IP address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsIP(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - ip := net.ParseIP(field.String()) - - return ip != nil -} - -// IsSSN is the validation function for validating if the field's value is a valid SSN. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsSSN(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if field.Len() != 11 { - return false - } - - return sSNRegex.MatchString(field.String()) -} - -// IsLongitude is the validation function for validating if the field's value is a valid longitude coordinate. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsLongitude(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return longitudeRegex.MatchString(field.String()) -} - -// IsLatitude is the validation function for validating if the field's value is a valid latitude coordinate. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsLatitude(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return latitudeRegex.MatchString(field.String()) -} - -// IsDataURI is the validation function for validating if the field's value is a valid data URI. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsDataURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - uri := strings.SplitN(field.String(), ",", 2) - - if len(uri) != 2 { - return false - } - - if !dataURIRegex.MatchString(uri[0]) { - return false - } - - fld := reflect.ValueOf(uri[1]) - - return IsBase64(v, topStruct, currentStructOrField, fld, fld.Type(), fld.Kind(), param) -} - -// HasMultiByteCharacter is the validation function for validating if the field's value has a multi byte character. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func HasMultiByteCharacter(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if field.Len() == 0 { - return true - } - - return multibyteRegex.MatchString(field.String()) -} - -// IsPrintableASCII is the validation function for validating if the field's value is a valid printable ASCII character. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsPrintableASCII(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return printableASCIIRegex.MatchString(field.String()) -} - -// IsASCII is the validation function for validating if the field's value is a valid ASCII character. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsASCII(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return aSCIIRegex.MatchString(field.String()) -} - -// IsUUID5 is the validation function for validating if the field's value is a valid v5 UUID. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsUUID5(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return uUID5Regex.MatchString(field.String()) -} - -// IsUUID4 is the validation function for validating if the field's value is a valid v4 UUID. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsUUID4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return uUID4Regex.MatchString(field.String()) -} - -// IsUUID3 is the validation function for validating if the field's value is a valid v3 UUID. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsUUID3(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return uUID3Regex.MatchString(field.String()) -} - -// IsUUID is the validation function for validating if the field's value is a valid UUID of any version. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsUUID(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return uUIDRegex.MatchString(field.String()) -} - -// IsISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsISBN(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return IsISBN10(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) || IsISBN13(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) -} - -// IsISBN13 is the validation function for validating if the field's value is a valid v13 ISBN. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsISBN13(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - s := strings.Replace(strings.Replace(field.String(), "-", "", 4), " ", "", 4) - - if !iSBN13Regex.MatchString(s) { - return false - } - - var checksum int32 - var i int32 - - factor := []int32{1, 3} - - for i = 0; i < 12; i++ { - checksum += factor[i%2] * int32(s[i]-'0') - } - - return (int32(s[12]-'0'))-((10-(checksum%10))%10) == 0 -} - -// IsISBN10 is the validation function for validating if the field's value is a valid v10 ISBN. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsISBN10(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - s := strings.Replace(strings.Replace(field.String(), "-", "", 3), " ", "", 3) - - if !iSBN10Regex.MatchString(s) { - return false - } - - var checksum int32 - var i int32 - - for i = 0; i < 9; i++ { - checksum += (i + 1) * int32(s[i]-'0') - } - - if s[9] == 'X' { - checksum += 10 * 10 - } else { - checksum += 10 * int32(s[9]-'0') - } - - return checksum%11 == 0 -} - -// ExcludesRune is the validation function for validating that the field's value does not contain the rune specified within the param. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func ExcludesRune(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return !ContainsRune(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) -} - -// ExcludesAll is the validation function for validating that the field's value does not contain any of the characters specified within the param. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func ExcludesAll(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return !ContainsAny(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) -} - -// Excludes is the validation function for validating that the field's value does not contain the text specified within the param. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func Excludes(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return !Contains(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) -} - -// ContainsRune is the validation function for validating that the field's value contains the rune specified within the param. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func ContainsRune(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - r, _ := utf8.DecodeRuneInString(param) - - return strings.ContainsRune(field.String(), r) -} - -// ContainsAny is the validation function for validating that the field's value contains any of the characters specified within the param. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func ContainsAny(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return strings.ContainsAny(field.String(), param) -} - -// Contains is the validation function for validating that the field's value contains the text specified within the param. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func Contains(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return strings.Contains(field.String(), param) -} - -// IsNeField is the validation function for validating if the current field's value is not equal to the field specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsNeField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param) - - if !ok || currentKind != fieldKind { - return true - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return field.Int() != currentField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return field.Uint() != currentField.Uint() - - case reflect.Float32, reflect.Float64: - return field.Float() != currentField.Float() - - case reflect.Slice, reflect.Map, reflect.Array: - return int64(field.Len()) != int64(currentField.Len()) - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != currentField.Type() { - return true - } - - if fieldType == timeType { - - t := currentField.Interface().(time.Time) - fieldTime := field.Interface().(time.Time) - - return !fieldTime.Equal(t) - } - - } - - // default reflect.String: - return field.String() != currentField.String() -} - -// IsNe is the validation function for validating that the field's value does not equal the provided param value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsNe(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return !IsEq(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) -} - -// IsLteCrossStructField is the validation function for validating if the current field's value is less than or equal to the field, within a separate struct, specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsLteCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - topField, topKind, ok := v.GetStructFieldOK(topStruct, param) - if !ok || topKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return field.Int() <= topField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return field.Uint() <= topField.Uint() - - case reflect.Float32, reflect.Float64: - return field.Float() <= topField.Float() - - case reflect.Slice, reflect.Map, reflect.Array: - return int64(field.Len()) <= int64(topField.Len()) - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != topField.Type() { - return false - } - - if fieldType == timeType { - - fieldTime := field.Interface().(time.Time) - topTime := topField.Interface().(time.Time) - - return fieldTime.Before(topTime) || fieldTime.Equal(topTime) - } - } - - // default reflect.String: - return field.String() <= topField.String() -} - -// IsLtCrossStructField is the validation function for validating if the current field's value is less than the field, within a separate struct, specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsLtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - topField, topKind, ok := v.GetStructFieldOK(topStruct, param) - if !ok || topKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return field.Int() < topField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return field.Uint() < topField.Uint() - - case reflect.Float32, reflect.Float64: - return field.Float() < topField.Float() - - case reflect.Slice, reflect.Map, reflect.Array: - return int64(field.Len()) < int64(topField.Len()) - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != topField.Type() { - return false - } - - if fieldType == timeType { - - fieldTime := field.Interface().(time.Time) - topTime := topField.Interface().(time.Time) - - return fieldTime.Before(topTime) - } - } - - // default reflect.String: - return field.String() < topField.String() -} - -// IsGteCrossStructField is the validation function for validating if the current field's value is greater than or equal to the field, within a separate struct, specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsGteCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - topField, topKind, ok := v.GetStructFieldOK(topStruct, param) - if !ok || topKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return field.Int() >= topField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return field.Uint() >= topField.Uint() - - case reflect.Float32, reflect.Float64: - return field.Float() >= topField.Float() - - case reflect.Slice, reflect.Map, reflect.Array: - return int64(field.Len()) >= int64(topField.Len()) - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != topField.Type() { - return false - } - - if fieldType == timeType { - - fieldTime := field.Interface().(time.Time) - topTime := topField.Interface().(time.Time) - - return fieldTime.After(topTime) || fieldTime.Equal(topTime) - } - } - - // default reflect.String: - return field.String() >= topField.String() -} - -// IsGtCrossStructField is the validation function for validating if the current field's value is greater than the field, within a separate struct, specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsGtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - topField, topKind, ok := v.GetStructFieldOK(topStruct, param) - if !ok || topKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return field.Int() > topField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return field.Uint() > topField.Uint() - - case reflect.Float32, reflect.Float64: - return field.Float() > topField.Float() - - case reflect.Slice, reflect.Map, reflect.Array: - return int64(field.Len()) > int64(topField.Len()) - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != topField.Type() { - return false - } - - if fieldType == timeType { - - fieldTime := field.Interface().(time.Time) - topTime := topField.Interface().(time.Time) - - return fieldTime.After(topTime) - } - } - - // default reflect.String: - return field.String() > topField.String() -} - -// IsNeCrossStructField is the validation function for validating that the current field's value is not equal to the field, within a separate struct, specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsNeCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - topField, currentKind, ok := v.GetStructFieldOK(topStruct, param) - if !ok || currentKind != fieldKind { - return true - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return topField.Int() != field.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return topField.Uint() != field.Uint() - - case reflect.Float32, reflect.Float64: - return topField.Float() != field.Float() - - case reflect.Slice, reflect.Map, reflect.Array: - return int64(topField.Len()) != int64(field.Len()) - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != topField.Type() { - return true - } - - if fieldType == timeType { - - t := field.Interface().(time.Time) - fieldTime := topField.Interface().(time.Time) - - return !fieldTime.Equal(t) - } - } - - // default reflect.String: - return topField.String() != field.String() -} - -// IsEqCrossStructField is the validation function for validating that the current field's value is equal to the field, within a separate struct, specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsEqCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - topField, topKind, ok := v.GetStructFieldOK(topStruct, param) - if !ok || topKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return topField.Int() == field.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return topField.Uint() == field.Uint() - - case reflect.Float32, reflect.Float64: - return topField.Float() == field.Float() - - case reflect.Slice, reflect.Map, reflect.Array: - return int64(topField.Len()) == int64(field.Len()) - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != topField.Type() { - return false - } - - if fieldType == timeType { - - t := field.Interface().(time.Time) - fieldTime := topField.Interface().(time.Time) - - return fieldTime.Equal(t) - } - } - - // default reflect.String: - return topField.String() == field.String() -} - -// IsEqField is the validation function for validating if the current field's value is equal to the field specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsEqField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param) - if !ok || currentKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return field.Int() == currentField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return field.Uint() == currentField.Uint() - - case reflect.Float32, reflect.Float64: - return field.Float() == currentField.Float() - - case reflect.Slice, reflect.Map, reflect.Array: - return int64(field.Len()) == int64(currentField.Len()) - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != currentField.Type() { - return false - } - - if fieldType == timeType { - - t := currentField.Interface().(time.Time) - fieldTime := field.Interface().(time.Time) - - return fieldTime.Equal(t) - } - - } - - // default reflect.String: - return field.String() == currentField.String() -} - -// IsEq is the validation function for validating if the current field's value is equal to the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsEq(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - switch fieldKind { - - case reflect.String: - return field.String() == param - - case reflect.Slice, reflect.Map, reflect.Array: - p := asInt(param) - - return int64(field.Len()) == p - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) - - return field.Int() == p - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p := asUint(param) - - return field.Uint() == p - - case reflect.Float32, reflect.Float64: - p := asFloat(param) - - return field.Float() == p - } - - panic(fmt.Sprintf("Bad field type %T", field.Interface())) -} - -// IsBase64 is the validation function for validating if the current field's value is a valid base 64. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsBase64(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return base64Regex.MatchString(field.String()) -} - -// IsURI is the validation function for validating if the current field's value is a valid URI. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - switch fieldKind { - - case reflect.String: - - s := field.String() - - // checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195 - // emulate browser and strip the '#' suffix prior to validation. see issue-#237 - if i := strings.Index(s, "#"); i > -1 { - s = s[:i] - } - - if s == blank { - return false - } - - _, err := url.ParseRequestURI(s) - - return err == nil - } - - panic(fmt.Sprintf("Bad field type %T", field.Interface())) -} - -// IsURL is the validation function for validating if the current field's value is a valid URL. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsURL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - switch fieldKind { - - case reflect.String: - - var i int - s := field.String() - - // checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195 - // emulate browser and strip the '#' suffix prior to validation. see issue-#237 - if i = strings.Index(s, "#"); i > -1 { - s = s[:i] - } - - if s == blank { - return false - } - - url, err := url.ParseRequestURI(s) - - if err != nil || url.Scheme == blank { - return false - } - - return err == nil - } - - panic(fmt.Sprintf("Bad field type %T", field.Interface())) -} - -// IsEmail is the validation function for validating if the current field's value is a valid email address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsEmail(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return emailRegex.MatchString(field.String()) -} - -// IsHSLA is the validation function for validating if the current field's value is a valid HSLA color. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsHSLA(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return hslaRegex.MatchString(field.String()) -} - -// IsHSL is the validation function for validating if the current field's value is a valid HSL color. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsHSL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return hslRegex.MatchString(field.String()) -} - -// IsRGBA is the validation function for validating if the current field's value is a valid RGBA color. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsRGBA(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return rgbaRegex.MatchString(field.String()) -} - -// IsRGB is the validation function for validating if the current field's value is a valid RGB color. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsRGB(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return rgbRegex.MatchString(field.String()) -} - -// IsHEXColor is the validation function for validating if the current field's value is a valid HEX color. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsHEXColor(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return hexcolorRegex.MatchString(field.String()) -} - -// IsHexadecimal is the validation function for validating if the current field's value is a valid hexadecimal. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsHexadecimal(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return hexadecimalRegex.MatchString(field.String()) -} - -// IsNumber is the validation function for validating if the current field's value is a valid number. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsNumber(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return numberRegex.MatchString(field.String()) -} - -// IsNumeric is the validation function for validating if the current field's value is a valid numeric value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsNumeric(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return numericRegex.MatchString(field.String()) -} - -// IsAlphanum is the validation function for validating if the current field's value is a valid alphanumeric value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsAlphanum(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return alphaNumericRegex.MatchString(field.String()) -} - -// IsAlpha is the validation function for validating if the current field's value is a valid alpha value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsAlpha(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return alphaRegex.MatchString(field.String()) -} - -// HasValue is the validation function for validating if the current field's value is not the default static value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func HasValue(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - switch fieldKind { - case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: - return !field.IsNil() - default: - return field.IsValid() && field.Interface() != reflect.Zero(fieldType).Interface() - } -} - -// IsGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsGteField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param) - if !ok || currentKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - - return field.Int() >= currentField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - - return field.Uint() >= currentField.Uint() - - case reflect.Float32, reflect.Float64: - - return field.Float() >= currentField.Float() - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != currentField.Type() { - return false - } - - if fieldType == timeType { - - t := currentField.Interface().(time.Time) - fieldTime := field.Interface().(time.Time) - - return fieldTime.After(t) || fieldTime.Equal(t) - } - } - - // default reflect.String - return len(field.String()) >= len(currentField.String()) -} - -// IsGtField is the validation function for validating if the current field's value is greater than the field specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsGtField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param) - if !ok || currentKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - - return field.Int() > currentField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - - return field.Uint() > currentField.Uint() - - case reflect.Float32, reflect.Float64: - - return field.Float() > currentField.Float() - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != currentField.Type() { - return false - } - - if fieldType == timeType { - - t := currentField.Interface().(time.Time) - fieldTime := field.Interface().(time.Time) - - return fieldTime.After(t) - } - } - - // default reflect.String - return len(field.String()) > len(currentField.String()) -} - -// IsGte is the validation function for validating if the current field's value is greater than or equal to the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsGte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - switch fieldKind { - - case reflect.String: - p := asInt(param) - - return int64(utf8.RuneCountInString(field.String())) >= p - - case reflect.Slice, reflect.Map, reflect.Array: - p := asInt(param) - - return int64(field.Len()) >= p - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) - - return field.Int() >= p - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p := asUint(param) - - return field.Uint() >= p - - case reflect.Float32, reflect.Float64: - p := asFloat(param) - - return field.Float() >= p - - case reflect.Struct: - - if fieldType == timeType || fieldType == timePtrType { - - now := time.Now().UTC() - t := field.Interface().(time.Time) - - return t.After(now) || t.Equal(now) - } - } - - panic(fmt.Sprintf("Bad field type %T", field.Interface())) -} - -// IsGt is the validation function for validating if the current field's value is greater than the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsGt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - switch fieldKind { - - case reflect.String: - p := asInt(param) - - return int64(utf8.RuneCountInString(field.String())) > p - - case reflect.Slice, reflect.Map, reflect.Array: - p := asInt(param) - - return int64(field.Len()) > p - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) - - return field.Int() > p - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p := asUint(param) - - return field.Uint() > p - - case reflect.Float32, reflect.Float64: - p := asFloat(param) - - return field.Float() > p - case reflect.Struct: - - if fieldType == timeType || fieldType == timePtrType { - - return field.Interface().(time.Time).After(time.Now().UTC()) - } - } - - panic(fmt.Sprintf("Bad field type %T", field.Interface())) -} - -// HasLengthOf is the validation function for validating if the current field's value is equal to the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func HasLengthOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - switch fieldKind { - - case reflect.String: - p := asInt(param) - - return int64(utf8.RuneCountInString(field.String())) == p - - case reflect.Slice, reflect.Map, reflect.Array: - p := asInt(param) - - return int64(field.Len()) == p - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) - - return field.Int() == p - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p := asUint(param) - - return field.Uint() == p - - case reflect.Float32, reflect.Float64: - p := asFloat(param) - - return field.Float() == p - } - - panic(fmt.Sprintf("Bad field type %T", field.Interface())) -} - -// HasMinOf is the validation function for validating if the current field's value is greater than or equal to the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func HasMinOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - return IsGte(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) -} - -// IsLteField is the validation function for validating if the current field's value is less than or equal to the field specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsLteField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param) - if !ok || currentKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - - return field.Int() <= currentField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - - return field.Uint() <= currentField.Uint() - - case reflect.Float32, reflect.Float64: - - return field.Float() <= currentField.Float() - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != currentField.Type() { - return false - } - - if fieldType == timeType { - - t := currentField.Interface().(time.Time) - fieldTime := field.Interface().(time.Time) - - return fieldTime.Before(t) || fieldTime.Equal(t) - } - } - - // default reflect.String - return len(field.String()) <= len(currentField.String()) -} - -// IsLtField is the validation function for validating if the current field's value is less than the field specified by the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsLtField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param) - if !ok || currentKind != fieldKind { - return false - } - - switch fieldKind { - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - - return field.Int() < currentField.Int() - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - - return field.Uint() < currentField.Uint() - - case reflect.Float32, reflect.Float64: - - return field.Float() < currentField.Float() - - case reflect.Struct: - - // Not Same underlying type i.e. struct and time - if fieldType != currentField.Type() { - return false - } - - if fieldType == timeType { - - t := currentField.Interface().(time.Time) - fieldTime := field.Interface().(time.Time) - - return fieldTime.Before(t) - } - } - - // default reflect.String - return len(field.String()) < len(currentField.String()) -} - -// IsLte is the validation function for validating if the current field's value is less than or equal to the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsLte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - switch fieldKind { - - case reflect.String: - p := asInt(param) - - return int64(utf8.RuneCountInString(field.String())) <= p - - case reflect.Slice, reflect.Map, reflect.Array: - p := asInt(param) - - return int64(field.Len()) <= p - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) - - return field.Int() <= p - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p := asUint(param) - - return field.Uint() <= p - - case reflect.Float32, reflect.Float64: - p := asFloat(param) - - return field.Float() <= p - - case reflect.Struct: - - if fieldType == timeType || fieldType == timePtrType { - - now := time.Now().UTC() - t := field.Interface().(time.Time) - - return t.Before(now) || t.Equal(now) - } - } - - panic(fmt.Sprintf("Bad field type %T", field.Interface())) -} - -// IsLt is the validation function for validating if the current field's value is less than the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsLt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - switch fieldKind { - - case reflect.String: - p := asInt(param) - - return int64(utf8.RuneCountInString(field.String())) < p - - case reflect.Slice, reflect.Map, reflect.Array: - p := asInt(param) - - return int64(field.Len()) < p - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) - - return field.Int() < p - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p := asUint(param) - - return field.Uint() < p - - case reflect.Float32, reflect.Float64: - p := asFloat(param) - - return field.Float() < p - - case reflect.Struct: - - if fieldType == timeType || fieldType == timePtrType { - - return field.Interface().(time.Time).Before(time.Now().UTC()) - } - } - - panic(fmt.Sprintf("Bad field type %T", field.Interface())) -} - -// HasMaxOf is the validation function for validating if the current field's value is less than or equal to the param's value. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func HasMaxOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - return IsLte(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) -} - -// IsTCP4AddrResolvable is the validation function for validating if the field's value is a resolvable tcp4 address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsTCP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) { - return false - } - - _, err := net.ResolveTCPAddr("tcp4", field.String()) - return err == nil -} - -// IsTCP6AddrResolvable is the validation function for validating if the field's value is a resolvable tcp6 address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsTCP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) { - return false - } - - _, err := net.ResolveTCPAddr("tcp6", field.String()) - return err == nil -} - -// IsTCPAddrResolvable is the validation function for validating if the field's value is a resolvable tcp address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsTCPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) && - !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) { - return false - } - - _, err := net.ResolveTCPAddr("tcp", field.String()) - return err == nil -} - -// IsUDP4AddrResolvable is the validation function for validating if the field's value is a resolvable udp4 address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsUDP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) { - return false - } - - _, err := net.ResolveUDPAddr("udp4", field.String()) - return err == nil -} - -// IsUDP6AddrResolvable is the validation function for validating if the field's value is a resolvable udp6 address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsUDP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) { - return false - } - - _, err := net.ResolveUDPAddr("udp6", field.String()) - return err == nil -} - -// IsUDPAddrResolvable is the validation function for validating if the field's value is a resolvable udp address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsUDPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) && - !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) { - return false - } - - _, err := net.ResolveUDPAddr("udp", field.String()) - return err == nil -} - -// IsIP4AddrResolvable is the validation function for validating if the field's value is a resolvable ip4 address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsIP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if !IsIPv4(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) { - return false - } - - _, err := net.ResolveIPAddr("ip4", field.String()) - return err == nil -} - -// IsIP6AddrResolvable is the validation function for validating if the field's value is a resolvable ip6 address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsIP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if !IsIPv6(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) { - return false - } - - _, err := net.ResolveIPAddr("ip6", field.String()) - return err == nil -} - -// IsIPAddrResolvable is the validation function for validating if the field's value is a resolvable ip address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsIPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if !IsIP(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) { - return false - } - - _, err := net.ResolveIPAddr("ip", field.String()) - return err == nil -} - -// IsUnixAddrResolvable is the validation function for validating if the field's value is a resolvable unix address. -// NOTE: This is exposed for use within your own custom functions and not intended to be called directly. -func IsUnixAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - _, err := net.ResolveUnixAddr("unix", field.String()) - return err == nil -} - -func isIP4Addr(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - val := field.String() - - if idx := strings.LastIndex(val, ":"); idx != -1 { - val = val[0:idx] - } - - if !IsIPv4(v, topStruct, currentStructOrField, reflect.ValueOf(val), fieldType, fieldKind, param) { - return false - } - - return true -} - -func isIP6Addr(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - val := field.String() - - if idx := strings.LastIndex(val, ":"); idx != -1 { - if idx != 0 && val[idx-1:idx] == "]" { - val = val[1 : idx-1] - } - } - - if !IsIPv6(v, topStruct, currentStructOrField, reflect.ValueOf(val), fieldType, fieldKind, param) { - return false - } - - return true -} diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/cache.go b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/cache.go deleted file mode 100644 index b3a8720..0000000 --- a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/cache.go +++ /dev/null @@ -1,285 +0,0 @@ -package validator - -import ( - "fmt" - "reflect" - "strings" - "sync" - "sync/atomic" -) - -type tagType uint8 - -const ( - typeDefault tagType = iota - typeOmitEmpty - typeNoStructLevel - typeStructOnly - typeDive - typeOr - typeExists -) - -type structCache struct { - lock sync.Mutex - m atomic.Value // map[reflect.Type]*cStruct -} - -func (sc *structCache) Get(key reflect.Type) (c *cStruct, found bool) { - c, found = sc.m.Load().(map[reflect.Type]*cStruct)[key] - return -} - -func (sc *structCache) Set(key reflect.Type, value *cStruct) { - - m := sc.m.Load().(map[reflect.Type]*cStruct) - - nm := make(map[reflect.Type]*cStruct, len(m)+1) - for k, v := range m { - nm[k] = v - } - nm[key] = value - sc.m.Store(nm) -} - -type tagCache struct { - lock sync.Mutex - m atomic.Value // map[string]*cTag -} - -func (tc *tagCache) Get(key string) (c *cTag, found bool) { - c, found = tc.m.Load().(map[string]*cTag)[key] - return -} - -func (tc *tagCache) Set(key string, value *cTag) { - - m := tc.m.Load().(map[string]*cTag) - - nm := make(map[string]*cTag, len(m)+1) - for k, v := range m { - nm[k] = v - } - nm[key] = value - tc.m.Store(nm) -} - -type cStruct struct { - Name string //结构体名称 - fields map[int]*cField //结构体对应的字段map - fn StructLevelFunc //结构体校验器 (结构体类型->结构体校验器) -} - -type cField struct { - Idx int //字段下标 - Name string //字段名 - AltName string // - cTags *cTag //Field对应的cTag规则,是一个链表(一串的规则). -} - -type cTag struct { - tag string //标签 - aliasTag string // - actualAliasTag string // - param string //如果是比较类型的标签,这里存放的是比较的值,比如说 min=10,这里存放的是【10】这个值 - hasAlias bool //是否有别名校验器标签 - typeof tagType //对应的tagType - hasTag bool //是否存在tag标签 - fn Func //当前cTag对应的【tag标签校验器】 - next *cTag //下一个cTag标签 -} - -func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStruct { - - v.structCache.lock.Lock() - defer v.structCache.lock.Unlock() // leave as defer! because if inner panics, it will never get unlocked otherwise! - - typ := current.Type() - - // could have been multiple trying to access, but once first is done this ensures struct - // isn't parsed again. - //read note 从缓存里面获取对应结构体类型的处理. - cs, ok := v.structCache.Get(typ) - if ok { - return cs - } - - //read note 如果缓存里面拿不到的话,就要从结构的Field中去解析 - cs = &cStruct{Name: sName, fields: make(map[int]*cField), fn: v.structLevelFuncs[typ]} - - numFields := current.NumField() - - var ctag *cTag - var fld reflect.StructField - var tag string - var customName string - - //read note 进行字段的处理 - for i := 0; i < numFields; i++ { - - fld = typ.Field(i) - - //read note 内嵌类型和小写的处理,直接pass - // 类似这种的: - /* type Derive struct { - Base ---内嵌 - } - */ - if !fld.Anonymous && fld.PkgPath != blank { - continue - } - - //read note 获取tag(通过之前Config设置的【tagName】属性去获取对应的tag) - tag = fld.Tag.Get(v.tagName) - - //read note 如果是忽略【-】的话,跳过 - if tag == skipValidationTag { - continue - } - - customName = fld.Name - - //read note config中【fieldNameTag】的处理,会设置到【cField】的【AltName】字段上,应该只是错误输出用的 - if v.fieldNameTag != blank { - - name := strings.SplitN(fld.Tag.Get(v.fieldNameTag), ",", 2)[0] - - // dash check is for json "-" (aka skipValidationTag) means don't output in json - if name != "" && name != skipValidationTag { - customName = name - } - } - - // NOTE: cannot use shared tag cache, because tags may be equal, but things like alias may be different - // and so only struct level caching can be used instead of combined with Field tag caching - - //read note struct层的校验规则和Field层的校验规则不能共用(标签可能相同,但是别名会不一样..) - - if len(tag) > 0 { - ctag, _ = v.parseFieldTagsRecursive(tag, fld.Name, blank, false) - } else { - // even if field doesn't have validations need cTag for traversing to potential inner/nested - // elements of the field. - ctag = new(cTag) - } - - cs.fields[i] = &cField{Idx: i, Name: fld.Name, AltName: customName, cTags: ctag} - } - - v.structCache.Set(typ, cs) - - return cs -} - -func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias string, hasAlias bool) (firstCtag *cTag, current *cTag) { - - var t string - var ok bool - noAlias := len(alias) == 0 - //read note:这边会把tag根据【,】进行分割处理,得到对应的tag组,所以我们在写的时候可以写入,分割的标签 - tags := strings.Split(tag, tagSeparator) - - for i := 0; i < len(tags); i++ { - - t = tags[i] - - if noAlias { - alias = t - } - - //read note 如果有别名校验器,则回去查找别名校验器(第一个和后面的设置不一样.调用next和没有调用next的区别) - if v.hasAliasValidators { - // check map for alias and process new tags, otherwise process as usual - if tagsVal, found := v.aliasValidators[t]; found { - - if i == 0 { - //read note 对别名校验器进行解析(一个子递归的过程.)除第一个校验器外,后面的校验器是通过一个next指向的链表连接起来 - firstCtag, current = v.parseFieldTagsRecursive(tagsVal, fieldName, t, true) - } else { - next, curr := v.parseFieldTagsRecursive(tagsVal, fieldName, t, true) - current.next, current = next, curr - - } - - continue - } - } - - //read note 设置对应的默认标签(第一个和后面的设置不一样.调用next和没有调用next的区别) - if i == 0 { - current = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true} - firstCtag = current - } else { - current.next = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true} - current = current.next - } - - //read note 判断用 【,】分割后的标签,前面几个是处理特殊标签的.如果不是特殊标签,则往下处理设置tag的值 - switch t { - case diveTag: - current.typeof = typeDive - continue - - case omitempty: - current.typeof = typeOmitEmpty - continue - - case structOnlyTag: - current.typeof = typeStructOnly - continue - - case noStructLevelTag: - current.typeof = typeNoStructLevel - continue - - case existsTag: - current.typeof = typeExists - continue - - default: - // if a pipe character is needed within the param you must use the utf8Pipe representation "0x7C" - orVals := strings.Split(t, orSeparator) - - //read note 或的条件进行拆分. - - for j := 0; j < len(orVals); j++ { - //read note 解析【=】标签 - vals := strings.SplitN(orVals[j], tagKeySeparator, 2) - - if noAlias { - alias = vals[0] - current.aliasTag = alias - } else { - current.actualAliasTag = t - } - - //read note 如果或的标签成立,也就是说 A|B|C ABC会组装成一个链(非头节点需要往下一个节点去处理,所以这边需要把current指向它的next) - if j > 0 { - current.next = &cTag{aliasTag: alias, actualAliasTag: current.actualAliasTag, hasAlias: hasAlias, hasTag: true} - current = current.next - } - - current.tag = vals[0] - if len(current.tag) == 0 { - panic(strings.TrimSpace(fmt.Sprintf(invalidValidation, fieldName))) - } - - //read note 查找对应的校验规则 - if current.fn, ok = v.validationFuncs[current.tag]; !ok { - panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, fieldName))) - } - - //read note 设置为typeOr.这个应该在后面处理对应字段的时候会拿到并且通过or的方式进行处理 - if len(orVals) > 1 { - current.typeof = typeOr - } - - if len(vals) > 1 { - current.param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1) - } - } - } - } - - return -} diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/doc.go b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/doc.go deleted file mode 100644 index fdede2c..0000000 --- a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/doc.go +++ /dev/null @@ -1,852 +0,0 @@ -/* -Package validator implements value validations for structs and individual fields -based on tags. - -It can also handle Cross-Field and Cross-Struct validation for nested structs -and has the ability to dive into arrays and maps of any type. - -Why not a better error message? -Because this library intends for you to handle your own error messages. - -Why should I handle my own errors? -Many reasons. We built an internationalized application and needed to know the -field, and what validation failed so we could provide a localized error. - - if fieldErr.Field == "Name" { - switch fieldErr.ErrorTag - case "required": - return "Translated string based on field + error" - default: - return "Translated string based on field" - } - - -Validation Functions Return Type error - -Doing things this way is actually the way the standard library does, see the -file.Open method here: - - https://golang.org/pkg/os/#Open. - -The authors return type "error" to avoid the issue discussed in the following, -where err is always != nil: - - http://stackoverflow.com/a/29138676/3158232 - https://github.com/go-playground/validator/issues/134 - -Validator only returns nil or ValidationErrors as type error; so, in your code -all you need to do is check if the error returned is not nil, and if it's not -type cast it to type ValidationErrors like so err.(validator.ValidationErrors). - -Custom Functions - -Custom functions can be added. Example: - - // Structure - func customFunc(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { - - if whatever { - return false - } - - return true - } - - validate.RegisterValidation("custom tag name", customFunc) - // NOTES: using the same tag name as an existing function - // will overwrite the existing one - -Cross-Field Validation - -Cross-Field Validation can be done via the following tags: - - eqfield - - nefield - - gtfield - - gtefield - - ltfield - - ltefield - - eqcsfield - - necsfield - - gtcsfield - - ftecsfield - - ltcsfield - - ltecsfield - -If, however, some custom cross-field validation is required, it can be done -using a custom validation. - -Why not just have cross-fields validation tags (i.e. only eqcsfield and not -eqfield)? - -The reason is efficiency. If you want to check a field within the same struct -"eqfield" only has to find the field on the same struct (1 level). But, if we -used "eqcsfield" it could be multiple levels down. Example: - - type Inner struct { - StartDate time.Time - } - - type Outer struct { - InnerStructField *Inner - CreatedAt time.Time `validate:"ltecsfield=InnerStructField.StartDate"` - } - - now := time.Now() - - inner := &Inner{ - StartDate: now, - } - - outer := &Outer{ - InnerStructField: inner, - CreatedAt: now, - } - - errs := validate.Struct(outer) - - // NOTE: when calling validate.Struct(val) topStruct will be the top level struct passed - // into the function - // when calling validate.FieldWithValue(val, field, tag) val will be - // whatever you pass, struct, field... - // when calling validate.Field(field, tag) val will be nil - -Multiple Validators - -Multiple validators on a field will process in the order defined. Example: - - type Test struct { - Field `validate:"max=10,min=1"` - } - - // max will be checked then min - -Bad Validator definitions are not handled by the library. Example: - - type Test struct { - Field `validate:"min=10,max=0"` - } - - // this definition of min max will never succeed - -Using Validator Tags - -Baked In Cross-Field validation only compares fields on the same struct. -If Cross-Field + Cross-Struct validation is needed you should implement your -own custom validator. - -Comma (",") is the default separator of validation tags. If you wish to -have a comma included within the parameter (i.e. excludesall=,) you will need to -use the UTF-8 hex representation 0x2C, which is replaced in the code as a comma, -so the above will become excludesall=0x2C. - - type Test struct { - Field `validate:"excludesall=,"` // BAD! Do not include a comma. - Field `validate:"excludesall=0x2C"` // GOOD! Use the UTF-8 hex representation. - } - -Pipe ("|") is the default separator of validation tags. If you wish to -have a pipe included within the parameter i.e. excludesall=| you will need to -use the UTF-8 hex representation 0x7C, which is replaced in the code as a pipe, -so the above will become excludesall=0x7C - - type Test struct { - Field `validate:"excludesall=|"` // BAD! Do not include a a pipe! - Field `validate:"excludesall=0x7C"` // GOOD! Use the UTF-8 hex representation. - } - - -Baked In Validators and Tags - -Here is a list of the current built in validators: - - -Skip Field - -Tells the validation to skip this struct field; this is particularly -handy in ignoring embedded structs from being validated. (Usage: -) - Usage: - - - -Or Operator - -This is the 'or' operator allowing multiple validators to be used and -accepted. (Usage: rbg|rgba) <-- this would allow either rgb or rgba -colors to be accepted. This can also be combined with 'and' for example -( Usage: omitempty,rgb|rgba) - - Usage: | - -StructOnly - -When a field that is a nested struct is encountered, and contains this flag -any validation on the nested struct will be run, but none of the nested -struct fields will be validated. This is usefull if inside of you program -you know the struct will be valid, but need to verify it has been assigned. -NOTE: only "required" and "omitempty" can be used on a struct itself. - - Usage: structonly - -NoStructLevel - -Same as structonly tag except that any struct level validations will not run. - - Usage: nostructlevel - -Exists - -Is a special tag without a validation function attached. It is used when a field -is a Pointer, Interface or Invalid and you wish to validate that it exists. -Example: want to ensure a bool exists if you define the bool as a pointer and -use exists it will ensure there is a value; couldn't use required as it would -fail when the bool was false. exists will fail is the value is a Pointer, Interface -or Invalid and is nil. - - Usage: exists - -Omit Empty - -Allows conditional validation, for example if a field is not set with -a value (Determined by the "required" validator) then other validation -such as min or max won't run, but if a value is set validation will run. - - Usage: omitempty - -Dive - -This tells the validator to dive into a slice, array or map and validate that -level of the slice, array or map with the validation tags that follow. -Multidimensional nesting is also supported, each level you wish to dive will -require another dive tag. - - Usage: dive - -Example #1 - - [][]string with validation tag "gt=0,dive,len=1,dive,required" - // gt=0 will be applied to [] - // len=1 will be applied to []string - // required will be applied to string - -Example #2 - - [][]string with validation tag "gt=0,dive,dive,required" - // gt=0 will be applied to [] - // []string will be spared validation - // required will be applied to string - -Required - -This validates that the value is not the data types default zero value. -For numbers ensures value is not zero. For strings ensures value is -not "". For slices, maps, pointers, interfaces, channels and functions -ensures the value is not nil. - - Usage: required - -Length - -For numbers, max will ensure that the value is -equal to the parameter given. For strings, it checks that -the string length is exactly that number of characters. For slices, -arrays, and maps, validates the number of items. - - Usage: len=10 - -Maximum - -For numbers, max will ensure that the value is -less than or equal to the parameter given. For strings, it checks -that the string length is at most that number of characters. For -slices, arrays, and maps, validates the number of items. - - Usage: max=10 - -Mininum - -For numbers, min will ensure that the value is -greater or equal to the parameter given. For strings, it checks that -the string length is at least that number of characters. For slices, -arrays, and maps, validates the number of items. - - Usage: min=10 - -Equals - -For strings & numbers, eq will ensure that the value is -equal to the parameter given. For slices, arrays, and maps, -validates the number of items. - - Usage: eq=10 - -Not Equal - -For strings & numbers, ne will ensure that the value is not -equal to the parameter given. For slices, arrays, and maps, -validates the number of items. - - Usage: ne=10 - -Greater Than - -For numbers, this will ensure that the value is greater than the -parameter given. For strings, it checks that the string length -is greater than that number of characters. For slices, arrays -and maps it validates the number of items. - -Example #1 - - Usage: gt=10 - -Example #2 (time.Time) - -For time.Time ensures the time value is greater than time.Now.UTC(). - - Usage: gt - -Greater Than or Equal - -Same as 'min' above. Kept both to make terminology with 'len' easier. - - -Example #1 - - Usage: gte=10 - -Example #2 (time.Time) - -For time.Time ensures the time value is greater than or equal to time.Now.UTC(). - - Usage: gte - -Less Than - -For numbers, this will ensure that the value is less than the parameter given. -For strings, it checks that the string length is less than that number of -characters. For slices, arrays, and maps it validates the number of items. - -Example #1 - - Usage: lt=10 - -Example #2 (time.Time) -For time.Time ensures the time value is less than time.Now.UTC(). - - Usage: lt - -Less Than or Equal - -Same as 'max' above. Kept both to make terminology with 'len' easier. - -Example #1 - - Usage: lte=10 - -Example #2 (time.Time) - -For time.Time ensures the time value is less than or equal to time.Now.UTC(). - - Usage: lte - -Field Equals Another Field - -This will validate the field value against another fields value either within -a struct or passed in field. - -Example #1: - - // Validation on Password field using: - Usage: eqfield=ConfirmPassword - -Example #2: - - // Validating by field: - validate.FieldWithValue(password, confirmpassword, "eqfield") - -Field Equals Another Field (relative) - -This does the same as eqfield except that it validates the field provided relative -to the top level struct. - - Usage: eqcsfield=InnerStructField.Field) - -Field Does Not Equal Another Field - -This will validate the field value against another fields value either within -a struct or passed in field. - -Examples: - - // Confirm two colors are not the same: - // - // Validation on Color field: - Usage: nefield=Color2 - - // Validating by field: - validate.FieldWithValue(color1, color2, "nefield") - -Field Does Not Equal Another Field (relative) - -This does the same as nefield except that it validates the field provided -relative to the top level struct. - - Usage: necsfield=InnerStructField.Field - -Field Greater Than Another Field - -Only valid for Numbers and time.Time types, this will validate the field value -against another fields value either within a struct or passed in field. -usage examples are for validation of a Start and End date: - -Example #1: - - // Validation on End field using: - validate.Struct Usage(gtfield=Start) - -Example #2: - - // Validating by field: - validate.FieldWithValue(start, end, "gtfield") - - -Field Greater Than Another Relative Field - -This does the same as gtfield except that it validates the field provided -relative to the top level struct. - - Usage: gtcsfield=InnerStructField.Field - -Field Greater Than or Equal To Another Field - -Only valid for Numbers and time.Time types, this will validate the field value -against another fields value either within a struct or passed in field. -usage examples are for validation of a Start and End date: - -Example #1: - - // Validation on End field using: - validate.Struct Usage(gtefield=Start) - -Example #2: - - // Validating by field: - validate.FieldWithValue(start, end, "gtefield") - -Field Greater Than or Equal To Another Relative Field - -This does the same as gtefield except that it validates the field provided relative -to the top level struct. - - Usage: gtecsfield=InnerStructField.Field - -Less Than Another Field - -Only valid for Numbers and time.Time types, this will validate the field value -against another fields value either within a struct or passed in field. -usage examples are for validation of a Start and End date: - -Example #1: - - // Validation on End field using: - validate.Struct Usage(ltfield=Start) - -Example #2: - - // Validating by field: - validate.FieldWithValue(start, end, "ltfield") - -Less Than Another Relative Field - -This does the same as ltfield except that it validates the field provided relative -to the top level struct. - - Usage: ltcsfield=InnerStructField.Field - -Less Than or Equal To Another Field - -Only valid for Numbers and time.Time types, this will validate the field value -against another fields value either within a struct or passed in field. -usage examples are for validation of a Start and End date: - -Example #1: - - // Validation on End field using: - validate.Struct Usage(ltefield=Start) - -Example #2: - - // Validating by field: - validate.FieldWithValue(start, end, "ltefield") - -Less Than or Equal To Another Relative Field - -This does the same as ltefield except that it validates the field provided relative -to the top level struct. - - Usage: ltecsfield=InnerStructField.Field - -Alpha Only - -This validates that a string value contains alpha characters only - - Usage: alpha - -Alphanumeric - -This validates that a string value contains alphanumeric characters only - - Usage: alphanum - -Numeric - -This validates that a string value contains a basic numeric value. -basic excludes exponents etc... - - Usage: numeric - -Hexadecimal String - -This validates that a string value contains a valid hexadecimal. - - Usage: hexadecimal - -Hexcolor String - -This validates that a string value contains a valid hex color including -hashtag (#) - - Usage: hexcolor - -RGB String - -This validates that a string value contains a valid rgb color - - Usage: rgb - -RGBA String - -This validates that a string value contains a valid rgba color - - Usage: rgba - -HSL String - -This validates that a string value contains a valid hsl color - - Usage: hsl - -HSLA String - -This validates that a string value contains a valid hsla color - - Usage: hsla - -E-mail String - -This validates that a string value contains a valid email -This may not conform to all possibilities of any rfc standard, but neither -does any email provider accept all posibilities. - - Usage: email - -URL String - -This validates that a string value contains a valid url -This will accept any url the golang request uri accepts but must contain -a schema for example http:// or rtmp:// - - Usage: url - -URI String - -This validates that a string value contains a valid uri -This will accept any uri the golang request uri accepts - - Usage: uri - -Base64 String - -This validates that a string value contains a valid base64 value. -Although an empty string is valid base64 this will report an empty string -as an error, if you wish to accept an empty string as valid you can use -this with the omitempty tag. - - Usage: base64 - -Contains - -This validates that a string value contains the substring value. - - Usage: contains=@ - -Contains Any - -This validates that a string value contains any Unicode code points -in the substring value. - - Usage: containsany=!@#? - -Contains Rune - -This validates that a string value contains the supplied rune value. - - Usage: containsrune=@ - -Excludes - -This validates that a string value does not contain the substring value. - - Usage: excludes=@ - -Excludes All - -This validates that a string value does not contain any Unicode code -points in the substring value. - - Usage: excludesall=!@#? - -Excludes Rune - -This validates that a string value does not contain the supplied rune value. - - Usage: excludesrune=@ - -International Standard Book Number - -This validates that a string value contains a valid isbn10 or isbn13 value. - - Usage: isbn - -International Standard Book Number 10 - -This validates that a string value contains a valid isbn10 value. - - Usage: isbn10 - -International Standard Book Number 13 - -This validates that a string value contains a valid isbn13 value. - - Usage: isbn13 - - -Universally Unique Identifier UUID - -This validates that a string value contains a valid UUID. - - Usage: uuid - -Universally Unique Identifier UUID v3 - -This validates that a string value contains a valid version 3 UUID. - - Usage: uuid3 - -Universally Unique Identifier UUID v4 - -This validates that a string value contains a valid version 4 UUID. - - Usage: uuid4 - -Universally Unique Identifier UUID v5 - -This validates that a string value contains a valid version 5 UUID. - - Usage: uuid5 - -ASCII - -This validates that a string value contains only ASCII characters. -NOTE: if the string is blank, this validates as true. - - Usage: ascii - -Printable ASCII - -This validates that a string value contains only printable ASCII characters. -NOTE: if the string is blank, this validates as true. - - Usage: asciiprint - -Multi-Byte Characters - -This validates that a string value contains one or more multibyte characters. -NOTE: if the string is blank, this validates as true. - - Usage: multibyte - -Data URL - -This validates that a string value contains a valid DataURI. -NOTE: this will also validate that the data portion is valid base64 - - Usage: datauri - -Latitude - -This validates that a string value contains a valid latitude. - - Usage: latitude - -Longitude - -This validates that a string value contains a valid longitude. - - Usage: longitude - -Social Security Number SSN - -This validates that a string value contains a valid U.S. Social Security Number. - - Usage: ssn - -Internet Protocol Address IP - -This validates that a string value contains a valid IP Adress. - - Usage: ip - -Internet Protocol Address IPv4 - -This validates that a string value contains a valid v4 IP Adress. - - Usage: ipv4 - -Internet Protocol Address IPv6 - -This validates that a string value contains a valid v6 IP Adress. - - Usage: ipv6 - -Classless Inter-Domain Routing CIDR - -This validates that a string value contains a valid CIDR Adress. - - Usage: cidr - -Classless Inter-Domain Routing CIDRv4 - -This validates that a string value contains a valid v4 CIDR Adress. - - Usage: cidrv4 - -Classless Inter-Domain Routing CIDRv6 - -This validates that a string value contains a valid v6 CIDR Adress. - - Usage: cidrv6 - -Transmission Control Protocol Address TCP - -This validates that a string value contains a valid resolvable TCP Adress. - - Usage: tcp_addr - -Transmission Control Protocol Address TCPv4 - -This validates that a string value contains a valid resolvable v4 TCP Adress. - - Usage: tcp4_addr - -Transmission Control Protocol Address TCPv6 - -This validates that a string value contains a valid resolvable v6 TCP Adress. - - Usage: tcp6_addr - -User Datagram Protocol Address UDP - -This validates that a string value contains a valid resolvable UDP Adress. - - Usage: udp_addr - -User Datagram Protocol Address UDPv4 - -This validates that a string value contains a valid resolvable v4 UDP Adress. - - Usage: udp4_addr - -User Datagram Protocol Address UDPv6 - -This validates that a string value contains a valid resolvable v6 UDP Adress. - - Usage: udp6_addr - -Internet Protocol Address IP - -This validates that a string value contains a valid resolvable IP Adress. - - Usage: ip_addr - -Internet Protocol Address IPv4 - -This validates that a string value contains a valid resolvable v4 IP Adress. - - Usage: ip4_addr - -Internet Protocol Address IPv6 - -This validates that a string value contains a valid resolvable v6 IP Adress. - - Usage: ip6_addr - -Unix domain socket end point Address - -This validates that a string value contains a valid Unix Adress. - - Usage: unix_addr - -Media Access Control Address MAC - -This validates that a string value contains a valid MAC Adress. - - Usage: mac - -Note: See Go's ParseMAC for accepted formats and types: - - http://golang.org/src/net/mac.go?s=866:918#L29 - -Alias Validators and Tags - -NOTE: When returning an error, the tag returned in "FieldError" will be -the alias tag unless the dive tag is part of the alias. Everything after the -dive tag is not reported as the alias tag. Also, the "ActualTag" in the before -case will be the actual tag within the alias that failed. - -Here is a list of the current built in alias tags: - - "iscolor" - alias is "hexcolor|rgb|rgba|hsl|hsla" (Usage: iscolor) - -Validator notes: - - regex - a regex validator won't be added because commas and = signs can be part - of a regex which conflict with the validation definitions. Although - workarounds can be made, they take away from using pure regex's. - Furthermore it's quick and dirty but the regex's become harder to - maintain and are not reusable, so it's as much a programming philosiphy - as anything. - - In place of this new validator functions should be created; a regex can - be used within the validator function and even be precompiled for better - efficiency within regexes.go. - - And the best reason, you can submit a pull request and we can keep on - adding to the validation library of this package! - -Panics - -This package panics when bad input is provided, this is by design, bad code like -that should not make it to production. - - type Test struct { - TestField string `validate:"nonexistantfunction=1"` - } - - t := &Test{ - TestField: "Test" - } - - validate.Struct(t) // this will panic -*/ -package validator diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/logo.png b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/logo.png deleted file mode 100644 index 355000f..0000000 Binary files a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/logo.png and /dev/null differ diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/regexes.go b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/regexes.go deleted file mode 100644 index 83ae198..0000000 --- a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/regexes.go +++ /dev/null @@ -1,59 +0,0 @@ -package validator - -import "regexp" - -const ( - alphaRegexString = "^[a-zA-Z]+$" - alphaNumericRegexString = "^[a-zA-Z0-9]+$" - numericRegexString = "^[-+]?[0-9]+(?:\\.[0-9]+)?$" - numberRegexString = "^[0-9]+$" - hexadecimalRegexString = "^[0-9a-fA-F]+$" - hexcolorRegexString = "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$" - rgbRegexString = "^rgb\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*\\)$" - rgbaRegexString = "^rgba\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$" - hslRegexString = "^hsl\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*\\)$" - hslaRegexString = "^hsla\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$" - emailRegexString = "^(?:(?:(?:(?:[a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(?:\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|(?:(?:\\x22)(?:(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(?:\\x20|\\x09)+)?(?:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:\\(?:[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(\\x20|\\x09)+)?(?:\\x22)))@(?:(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$" - base64RegexString = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$" - iSBN10RegexString = "^(?:[0-9]{9}X|[0-9]{10})$" - iSBN13RegexString = "^(?:(?:97(?:8|9))[0-9]{10})$" - uUID3RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$" - uUID4RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" - uUID5RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" - uUIDRegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" - aSCIIRegexString = "^[\x00-\x7F]*$" - printableASCIIRegexString = "^[\x20-\x7E]*$" - multibyteRegexString = "[^\x00-\x7F]" - dataURIRegexString = "^data:.+\\/(.+);base64$" - latitudeRegexString = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$" - longitudeRegexString = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$" - sSNRegexString = `^\d{3}[- ]?\d{2}[- ]?\d{4}$` -) - -var ( - alphaRegex = regexp.MustCompile(alphaRegexString) - alphaNumericRegex = regexp.MustCompile(alphaNumericRegexString) - numericRegex = regexp.MustCompile(numericRegexString) - numberRegex = regexp.MustCompile(numberRegexString) - hexadecimalRegex = regexp.MustCompile(hexadecimalRegexString) - hexcolorRegex = regexp.MustCompile(hexcolorRegexString) - rgbRegex = regexp.MustCompile(rgbRegexString) - rgbaRegex = regexp.MustCompile(rgbaRegexString) - hslRegex = regexp.MustCompile(hslRegexString) - hslaRegex = regexp.MustCompile(hslaRegexString) - emailRegex = regexp.MustCompile(emailRegexString) - base64Regex = regexp.MustCompile(base64RegexString) - iSBN10Regex = regexp.MustCompile(iSBN10RegexString) - iSBN13Regex = regexp.MustCompile(iSBN13RegexString) - uUID3Regex = regexp.MustCompile(uUID3RegexString) - uUID4Regex = regexp.MustCompile(uUID4RegexString) - uUID5Regex = regexp.MustCompile(uUID5RegexString) - uUIDRegex = regexp.MustCompile(uUIDRegexString) - aSCIIRegex = regexp.MustCompile(aSCIIRegexString) - printableASCIIRegex = regexp.MustCompile(printableASCIIRegexString) - multibyteRegex = regexp.MustCompile(multibyteRegexString) - dataURIRegex = regexp.MustCompile(dataURIRegexString) - latitudeRegex = regexp.MustCompile(latitudeRegexString) - longitudeRegex = regexp.MustCompile(longitudeRegexString) - sSNRegex = regexp.MustCompile(sSNRegexString) -) diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/util.go b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/util.go deleted file mode 100644 index 08f691c..0000000 --- a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/util.go +++ /dev/null @@ -1,253 +0,0 @@ -package validator - -import ( - "reflect" - "strconv" - "strings" -) - -const ( - blank = "" - namespaceSeparator = "." - leftBracket = "[" - rightBracket = "]" - restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}" - restrictedAliasErr = "Alias '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation" - restrictedTagErr = "Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation" -) - -var ( - restrictedTags = map[string]struct{}{ - diveTag: {}, - existsTag: {}, - structOnlyTag: {}, - omitempty: {}, - skipValidationTag: {}, - utf8HexComma: {}, - utf8Pipe: {}, - noStructLevelTag: {}, - } -) - -// ExtractType gets the actual underlying type of field value. -// It will dive into pointers, customTypes and return you the -// underlying value and it's kind. -// it is exposed for use within you Custom Functions -func (v *Validate) ExtractType(current reflect.Value) (reflect.Value, reflect.Kind) { - - val, k, _ := v.extractTypeInternal(current, false) - return val, k -} - -// only exists to not break backward compatibility, needed to return the third param for a bug fix internally -func (v *Validate) extractTypeInternal(current reflect.Value, nullable bool) (reflect.Value, reflect.Kind, bool) { - - switch current.Kind() { - case reflect.Ptr: - - nullable = true - - if current.IsNil() { - return current, reflect.Ptr, nullable - } - - return v.extractTypeInternal(current.Elem(), nullable) - - case reflect.Interface: - - nullable = true - - if current.IsNil() { - return current, reflect.Interface, nullable - } - - return v.extractTypeInternal(current.Elem(), nullable) - - case reflect.Invalid: - return current, reflect.Invalid, nullable - - default: - - if v.hasCustomFuncs { - - if fn, ok := v.customTypeFuncs[current.Type()]; ok { - //read note 如果有自定义的类型校验器,则这边会先去调用一下类型校验器,然后在返回对应的结构体值,继续往回上一层,往下校验 - return v.extractTypeInternal(reflect.ValueOf(fn(current)), nullable) - } - } - - return current, current.Kind(), nullable - } -} - -// GetStructFieldOK traverses a struct to retrieve a specific field denoted by the provided namespace and -// returns the field, field kind and whether is was successful in retrieving the field at all. -// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field -// could not be retrieved because it didn't exist. -func (v *Validate) GetStructFieldOK(current reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) { - - current, kind := v.ExtractType(current) - - if kind == reflect.Invalid { - return current, kind, false - } - - if namespace == blank { - return current, kind, true - } - - switch kind { - - case reflect.Ptr, reflect.Interface: - - return current, kind, false - - case reflect.Struct: - - typ := current.Type() - fld := namespace - ns := namespace - - if typ != timeType && typ != timePtrType { - - idx := strings.Index(namespace, namespaceSeparator) - - if idx != -1 { - fld = namespace[:idx] - ns = namespace[idx+1:] - } else { - ns = blank - } - - bracketIdx := strings.Index(fld, leftBracket) - if bracketIdx != -1 { - fld = fld[:bracketIdx] - - ns = namespace[bracketIdx:] - } - - current = current.FieldByName(fld) - - return v.GetStructFieldOK(current, ns) - } - - case reflect.Array, reflect.Slice: - idx := strings.Index(namespace, leftBracket) - idx2 := strings.Index(namespace, rightBracket) - - arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2]) - - if arrIdx >= current.Len() { - return current, kind, false - } - - startIdx := idx2 + 1 - - if startIdx < len(namespace) { - if namespace[startIdx:startIdx+1] == namespaceSeparator { - startIdx++ - } - } - - return v.GetStructFieldOK(current.Index(arrIdx), namespace[startIdx:]) - - case reflect.Map: - idx := strings.Index(namespace, leftBracket) + 1 - idx2 := strings.Index(namespace, rightBracket) - - endIdx := idx2 - - if endIdx+1 < len(namespace) { - if namespace[endIdx+1:endIdx+2] == namespaceSeparator { - endIdx++ - } - } - - key := namespace[idx:idx2] - - switch current.Type().Key().Kind() { - case reflect.Int: - i, _ := strconv.Atoi(key) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:]) - case reflect.Int8: - i, _ := strconv.ParseInt(key, 10, 8) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(int8(i))), namespace[endIdx+1:]) - case reflect.Int16: - i, _ := strconv.ParseInt(key, 10, 16) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(int16(i))), namespace[endIdx+1:]) - case reflect.Int32: - i, _ := strconv.ParseInt(key, 10, 32) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(int32(i))), namespace[endIdx+1:]) - case reflect.Int64: - i, _ := strconv.ParseInt(key, 10, 64) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:]) - case reflect.Uint: - i, _ := strconv.ParseUint(key, 10, 0) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(uint(i))), namespace[endIdx+1:]) - case reflect.Uint8: - i, _ := strconv.ParseUint(key, 10, 8) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(uint8(i))), namespace[endIdx+1:]) - case reflect.Uint16: - i, _ := strconv.ParseUint(key, 10, 16) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(uint16(i))), namespace[endIdx+1:]) - case reflect.Uint32: - i, _ := strconv.ParseUint(key, 10, 32) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(uint32(i))), namespace[endIdx+1:]) - case reflect.Uint64: - i, _ := strconv.ParseUint(key, 10, 64) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:]) - case reflect.Float32: - f, _ := strconv.ParseFloat(key, 32) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(float32(f))), namespace[endIdx+1:]) - case reflect.Float64: - f, _ := strconv.ParseFloat(key, 64) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(f)), namespace[endIdx+1:]) - case reflect.Bool: - b, _ := strconv.ParseBool(key) - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(b)), namespace[endIdx+1:]) - - // reflect.Type = string - default: - return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(key)), namespace[endIdx+1:]) - } - } - - // if got here there was more namespace, cannot go any deeper - panic("Invalid field namespace") -} - -// asInt returns the parameter as a int64 -// or panics if it can't convert -func asInt(param string) int64 { - - i, err := strconv.ParseInt(param, 0, 64) - panicIf(err) - - return i -} - -// asUint returns the parameter as a uint64 -// or panics if it can't convert -func asUint(param string) uint64 { - - i, err := strconv.ParseUint(param, 0, 64) - panicIf(err) - - return i -} - -// asFloat returns the parameter as a float64 -// or panics if it can't convert -func asFloat(param string) float64 { - - i, err := strconv.ParseFloat(param, 64) - panicIf(err) - - return i -} - -func panicIf(err error) { - if err != nil { - panic(err.Error()) - } -} diff --git a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/validator.go b/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/validator.go deleted file mode 100644 index fde5326..0000000 --- a/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/validator.go +++ /dev/null @@ -1,829 +0,0 @@ -/** - * Package validator - * - * MISC: - * - anonymous structs - they don't have names so expect the Struct name within StructErrors to be blank - * - */ - -package validator - -import ( - "bytes" - "errors" - "fmt" - "reflect" - "strings" - "sync" - "time" -) - -const ( - utf8HexComma = "0x2C" //read note 在tag里面代表【,】;需要这么书写,直接写【,】会被识别成分割符 - utf8Pipe = "0x7C" //read note 在tag里面代表【|】;需要这么书写,直接写【|】会被识别成条件符 - tagSeparator = "," //read note tag标签分割符 - orSeparator = "|" //read note tag判断条件【或】 - tagKeySeparator = "=" //read note tag里面需要等值 使用= - - structOnlyTag = "structonly" //read note 结构体上有的tagType,因为结构体的特殊性,他在获取cTag的时候是从第二个开始的 - _ // 也就是说第二个才是生效的,所以当只书写structonly的时候,他会略过这个tag,那么必须跟着前面的一个标签才行,比如说 `valid="require,structonly"`,这样才会生效 - noStructLevelTag = "nostructlevel" // 同上 - - omitempty = "omitempty" //read note 如果字段未设值则忽略它 - skipValidationTag = "-" //read note 忽略字段 - diveTag = "dive" //read note 深入到slice, array or map 里面去校验里面的字段是否正确,每一层都需要多一个【div】来标识 - _ //read note 比如说 [][]string "gt=0,dive,dive,required" gt是校验[][]string长度,第一个div是校验[]string,第二个div是校验string - existsTag = "exists" //read note 校验值存在即可(除非是nil则会报错),和require的区别是说,require对默认值也会报错 - - //read note 数组结构的名称组成 - arrayIndexFieldName = "%s" + leftBracket + "%d" + rightBracket - mapIndexFieldName = "%s" + leftBracket + "%v" + rightBracket - - //read note 字段校验错误信息打印 - fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag" - //read note 报错信息(非字段校验错误) - invalidValidation = "Invalid validation tag on field %s" - undefinedValidation = "Undefined validation function on field %s" - validatorNotInitialized = "Validator instance not initialized" - fieldNameRequired = "Field Name Required" - tagRequired = "Tag Required" -) - -var ( - timeType = reflect.TypeOf(time.Time{}) - timePtrType = reflect.TypeOf(&time.Time{}) - defaultCField = new(cField) -) - -// StructLevel contains all of the information and helper methods -// for reporting errors during struct level validation -type StructLevel struct { - TopStruct reflect.Value - CurrentStruct reflect.Value - errPrefix string - nsPrefix string - errs ValidationErrors - v *Validate -} - -// ReportValidationErrors accepts the key relative to the top level struct and validatin errors. -// Example: had a triple nested struct User, ContactInfo, Country and ran errs := validate.Struct(country) -// from within a User struct level validation would call this method like so: -// ReportValidationErrors("ContactInfo.", errs) -// NOTE: relativeKey can contain both the Field Relative and Custom name relative paths -// i.e. ReportValidationErrors("ContactInfo.|cInfo", errs) where cInfo represents say the JSON name of -// the relative path; this will be split into 2 variables in the next valiator version. -func (sl *StructLevel) ReportValidationErrors(relativeKey string, errs ValidationErrors) { - for _, e := range errs { - - idx := strings.Index(relativeKey, "|") - var rel string - var cRel string - - if idx != -1 { - rel = relativeKey[:idx] - cRel = relativeKey[idx+1:] - } else { - rel = relativeKey - } - - key := sl.errPrefix + rel + e.Field - - e.FieldNamespace = key - e.NameNamespace = sl.nsPrefix + cRel + e.Name - - sl.errs[key] = e - } -} - -// ReportError reports an error just by passing the field and tag information -// NOTE: tag can be an existing validation tag or just something you make up -// and precess on the flip side it's up to you. -func (sl *StructLevel) ReportError(field reflect.Value, fieldName string, customName string, tag string) { - - field, kind := sl.v.ExtractType(field) - - if fieldName == blank { - panic(fieldNameRequired) - } - - if customName == blank { - customName = fieldName - } - - if tag == blank { - panic(tagRequired) - } - - ns := sl.errPrefix + fieldName - - switch kind { - case reflect.Invalid: - sl.errs[ns] = &FieldError{ - FieldNamespace: ns, - NameNamespace: sl.nsPrefix + customName, - Name: customName, - Field: fieldName, - Tag: tag, - ActualTag: tag, - Param: blank, - Kind: kind, - } - default: - sl.errs[ns] = &FieldError{ - FieldNamespace: ns, - NameNamespace: sl.nsPrefix + customName, - Name: customName, - Field: fieldName, - Tag: tag, - ActualTag: tag, - Param: blank, - Value: field.Interface(), - Kind: kind, - Type: field.Type(), - } - } -} - -// Validate contains the validator settings passed in using the Config struct -type Validate struct { - tagName string //校验起作用的tag名 - fieldNameTag string // - validationFuncs map[string]Func //规则类型的校验 【tag标签】-> 校验规则 - structLevelFuncs map[reflect.Type]StructLevelFunc //规则结构体的校验 【结构体类型】-> 校验规则 - customTypeFuncs map[reflect.Type]CustomTypeFunc //类型校验器 【数据类型】-> 校验规则 - aliasValidators map[string]string //别名校验器 【别名匹配规则组合】-> 校验规则 - hasCustomFuncs bool //是否存在类型校验器 - hasAliasValidators bool //是否有别名校验器 - hasStructLevelFuncs bool //是否有结构体校验器 - tagCache *tagCache //tag对应的【校验规则方法】的缓存 - structCache *structCache //结构体对应的【校验规则方法】的缓存 - errsPool *sync.Pool //校验错误奖池 -} - -func (v *Validate) initCheck() { - if v == nil { - panic(validatorNotInitialized) - } -} - -// Config contains the options that a Validator instance will use. -// It is passed to the New() function -type Config struct { - TagName string - FieldNameTag string -} - -// CustomTypeFunc allows for overriding or adding custom field type handler functions -// field = field value of the type to return a value to be validated -// example Valuer from sql drive see https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29 -type CustomTypeFunc func(field reflect.Value) interface{} - -// Func accepts all values needed for file and cross field validation -// v = validator instance, needed but some built in functions for it's custom types -// topStruct = top level struct when validating by struct otherwise nil -// currentStruct = current level struct when validating by struct otherwise optional comparison value -// field = field value for validation -// param = parameter used in validation i.e. gt=0 param would be 0 -type Func func(v *Validate, topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldtype reflect.Type, fieldKind reflect.Kind, param string) bool - -// StructLevelFunc accepts all values needed for struct level validation -type StructLevelFunc func(v *Validate, structLevel *StructLevel) - -// ValidationErrors is a type of map[string]*FieldError -// it exists to allow for multiple errors to be passed from this library -// and yet still subscribe to the error interface -type ValidationErrors map[string]*FieldError - -// Error is intended for use in development + debugging and not intended to be a production error message. -// It allows ValidationErrors to subscribe to the Error interface. -// All information to create an error message specific to your application is contained within -// the FieldError found within the ValidationErrors map -func (ve ValidationErrors) Error() string { - - buff := bytes.NewBufferString(blank) - - for key, err := range ve { - buff.WriteString(fmt.Sprintf(fieldErrMsg, key, err.Field, err.Tag)) - buff.WriteString("\n") - } - - return strings.TrimSpace(buff.String()) -} - -// FieldError contains a single field's validation error along -// with other properties that may be needed for error message creation -type FieldError struct { - FieldNamespace string - NameNamespace string - Field string - Name string - Tag string - ActualTag string - Kind reflect.Kind - Type reflect.Type - Param string - Value interface{} -} - -// New creates a new Validate instance for use. -func New(config *Config) *Validate { - - //read note tag校验器缓存,初始化 - tc := new(tagCache) - tc.m.Store(make(map[string]*cTag)) - - //read note 结构体缓存,初始化一个Map,防止后面添加的时候报错 - sc := new(structCache) - sc.m.Store(make(map[reflect.Type]*cStruct)) - - v := &Validate{ - tagName: config.TagName, - fieldNameTag: config.FieldNameTag, - tagCache: tc, - structCache: sc, - //read note 自定义一个错误池 - errsPool: &sync.Pool{New: func() interface{} { - return ValidationErrors{} - }}} - - //read note 设置别名规则类(一组) 可参考: baked_in.go/bakedInAliasValidators - if len(v.aliasValidators) == 0 { - // must copy alias validators for separate validations to be used in each validator instance - v.aliasValidators = map[string]string{} - for k, val := range bakedInAliasValidators { - //read note 默认别名校验器注册 - v.RegisterAliasValidation(k, val) - } - } - - //read note 设置默认的校验方法.可参考: baked_in.go/bakedInValidators - if len(v.validationFuncs) == 0 { - // must copy validators for separate validations to be used in each instance - v.validationFuncs = map[string]Func{} - for k, val := range bakedInValidators { - //read note 默认tag校验器注册 - v.RegisterValidation(k, val) - } - } - - return v -} - -// RegisterStructValidation registers a StructLevelFunc against a number of types -// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation -func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) { - v.initCheck() - - if v.structLevelFuncs == nil { - v.structLevelFuncs = map[reflect.Type]StructLevelFunc{} - } - - for _, t := range types { - v.structLevelFuncs[reflect.TypeOf(t)] = fn - fmt.Println(reflect.TypeOf(t)) - } - - v.hasStructLevelFuncs = true -} - -// RegisterValidation adds a validation Func to a Validate's map of validators denoted by the key -// NOTE: if the key already exists, the previous validation function will be replaced. -// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation -func (v *Validate) RegisterValidation(key string, fn Func) error { - v.initCheck() - - if key == blank { - return errors.New("Function Key cannot be empty") - } - - if fn == nil { - return errors.New("Function cannot be empty") - } - - _, ok := restrictedTags[key] - - if ok || strings.ContainsAny(key, restrictedTagChars) { - panic(fmt.Sprintf(restrictedTagErr, key)) - } - - v.validationFuncs[key] = fn - - return nil -} - -// RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types -// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation -//read note 注册类型的校验器,应该在校验之前就注册完成,因为该注册方法不是线程安全的. -func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) { - v.initCheck() - - if v.customTypeFuncs == nil { - v.customTypeFuncs = map[reflect.Type]CustomTypeFunc{} - } - - for _, t := range types { - v.customTypeFuncs[reflect.TypeOf(t)] = fn - } - - v.hasCustomFuncs = true -} - -// RegisterAliasValidation registers a mapping of a single validationstag that -// defines a common or complex set of validation(s) to simplify adding validation -// to structs. NOTE: when returning an error the tag returned in FieldError will be -// the alias tag unless the dive tag is part of the alias; everything after the -// dive tag is not reported as the alias tag. Also the ActualTag in the before case -// will be the actual tag within the alias that failed. -// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation -func (v *Validate) RegisterAliasValidation(alias, tags string) { - v.initCheck() - - _, ok := restrictedTags[alias] - - if ok || strings.ContainsAny(alias, restrictedTagChars) { - panic(fmt.Sprintf(restrictedAliasErr, alias)) - } - - v.aliasValidators[alias] = tags - v.hasAliasValidators = true -} - -// Field validates a single field using tag style validation and returns nil or ValidationErrors as type error. -// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. -// NOTE: it returns ValidationErrors instead of a single FieldError because this can also -// validate Array, Slice and maps fields which may contain more than one error -//read note -func (v *Validate) Field(field interface{}, tag string) error { - v.initCheck() - - if len(tag) == 0 || tag == skipValidationTag { - return nil - } - - errs := v.errsPool.Get().(ValidationErrors) - fieldVal := reflect.ValueOf(field) - - //read note 从tag缓存中获取 tag标签对应的校验方法 - ctag, ok := v.tagCache.Get(tag) - if !ok { - //read note 加锁 - v.tagCache.lock.Lock() - defer v.tagCache.lock.Unlock() - - // could have been multiple trying to access, but once first is done this ensures tag - // isn't parsed again. - //read note 加锁之后在这边再获取一次,因为在上一次判断到加锁的过程中,可能有函数已经把对应方法加载进来了 - ctag, ok = v.tagCache.Get(tag) - if !ok { - //read note - ctag, _ = v.parseFieldTagsRecursive(tag, blank, blank, false) - //read note 进行标签设值 - v.tagCache.Set(tag, ctag) - } - } - - v.traverseField(fieldVal, fieldVal, fieldVal, blank, blank, errs, false, false, nil, nil, defaultCField, ctag) - - //read note 判断校验错误是否存在 - if len(errs) == 0 { - v.errsPool.Put(errs) - return nil - } - - return errs -} - -// FieldWithValue validates a single field, against another fields value using tag style validation and returns nil or ValidationErrors. -// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. -// NOTE: it returns ValidationErrors instead of a single FieldError because this can also -// validate Array, Slice and maps fields which may contain more than one error -func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string) error { - v.initCheck() - - if len(tag) == 0 || tag == skipValidationTag { - return nil - } - - errs := v.errsPool.Get().(ValidationErrors) - topVal := reflect.ValueOf(val) - - ctag, ok := v.tagCache.Get(tag) - if !ok { - v.tagCache.lock.Lock() - defer v.tagCache.lock.Unlock() - - // could have been multiple trying to access, but once first is done this ensures tag - // isn't parsed again. - ctag, ok = v.tagCache.Get(tag) - if !ok { - ctag, _ = v.parseFieldTagsRecursive(tag, blank, blank, false) - v.tagCache.Set(tag, ctag) - } - } - - v.traverseField(topVal, topVal, reflect.ValueOf(field), blank, blank, errs, false, false, nil, nil, defaultCField, ctag) - - if len(errs) == 0 { - v.errsPool.Put(errs) - return nil - } - - return errs -} - -// StructPartial validates the fields passed in only, ignoring all others. -// Fields may be provided in a namespaced fashion relative to the struct provided -// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name and returns nil or ValidationErrors as error -// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. -func (v *Validate) StructPartial(current interface{}, fields ...string) error { - v.initCheck() - - sv, _ := v.ExtractType(reflect.ValueOf(current)) - name := sv.Type().Name() - m := map[string]struct{}{} - - if fields != nil { - for _, k := range fields { - - flds := strings.Split(k, namespaceSeparator) - if len(flds) > 0 { - - key := name + namespaceSeparator - for _, s := range flds { - - idx := strings.Index(s, leftBracket) - - if idx != -1 { - for idx != -1 { - key += s[:idx] - m[key] = struct{}{} - - idx2 := strings.Index(s, rightBracket) - idx2++ - key += s[idx:idx2] - m[key] = struct{}{} - s = s[idx2:] - idx = strings.Index(s, leftBracket) - } - } else { - - key += s - m[key] = struct{}{} - } - - key += namespaceSeparator - } - } - } - } - - errs := v.errsPool.Get().(ValidationErrors) - - v.ensureValidStruct(sv, sv, sv, blank, blank, errs, true, len(m) != 0, false, m, false) - - if len(errs) == 0 { - v.errsPool.Put(errs) - return nil - } - - return errs -} - -// StructExcept validates all fields except the ones passed in. -// Fields may be provided in a namespaced fashion relative to the struct provided -// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name and returns nil or ValidationErrors as error -// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. -func (v *Validate) StructExcept(current interface{}, fields ...string) error { - v.initCheck() - - sv, _ := v.ExtractType(reflect.ValueOf(current)) - name := sv.Type().Name() - m := map[string]struct{}{} - - for _, key := range fields { - m[name+namespaceSeparator+key] = struct{}{} - } - - errs := v.errsPool.Get().(ValidationErrors) - - v.ensureValidStruct(sv, sv, sv, blank, blank, errs, true, len(m) != 0, true, m, false) - - if len(errs) == 0 { - v.errsPool.Put(errs) - return nil - } - - return errs -} - -// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified. -// it returns nil or ValidationErrors as error. -// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors. -func (v *Validate) Struct(current interface{}) error { - v.initCheck() - - errs := v.errsPool.Get().(ValidationErrors) - sv := reflect.ValueOf(current) - - //read note 进行结构体校验 - v.ensureValidStruct(sv, sv, sv, blank, blank, errs, true, false, false, nil, false) - - //read note 校验之后,对校验错误进行处理. - if len(errs) == 0 { - v.errsPool.Put(errs) - return nil - } - - return errs -} - -func (v *Validate) ensureValidStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, useStructName bool, partial bool, exclude bool, includeExclude map[string]struct{}, isStructOnly bool) { - - //read note 指针处理成结构体Value(返回其指向的实际结构体) - if current.Kind() == reflect.Ptr && !current.IsNil() { - current = current.Elem() - } - - //read note 结构体类型校验. - if current.Kind() != reflect.Struct && current.Kind() != reflect.Interface { - panic("value passed for validation is not a struct") - } - - //read note 校验结构体 - v.tranverseStruct(topStruct, currentStruct, current, errPrefix, nsPrefix, errs, useStructName, partial, exclude, includeExclude, nil, nil) -} - -// tranverseStruct traverses a structs fields and then passes them to be validated by traverseField -func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, useStructName bool, partial bool, exclude bool, includeExclude map[string]struct{}, cs *cStruct, ct *cTag) { - - var ok bool - first := len(nsPrefix) == 0 - typ := current.Type() - - //read note 结构体校验器_缓存 - cs, ok = v.structCache.Get(typ) - if !ok { - cs = v.extractStructCache(current, typ.Name()) - } - - if useStructName { - errPrefix += cs.Name + namespaceSeparator - - if len(v.fieldNameTag) != 0 { - nsPrefix += cs.Name + namespaceSeparator - } - } - - // structonly tag present don't tranverseFields - // but must still check and run below struct level validation - // if present - //read note 【structonly】标签会忽略掉Field的校验 - if first || ct == nil || ct.typeof != typeStructOnly { - - for _, f := range cs.fields { - - if partial { - - _, ok = includeExclude[errPrefix+f.Name] - - if (ok && exclude) || (!ok && !exclude) { - continue - } - } - - v.traverseField(topStruct, currentStruct, current.Field(f.Idx), errPrefix, nsPrefix, errs, partial, exclude, includeExclude, cs, f, f.cTags) - } - } - - // check if any struct level validations, after all field validations already checked. - //read note 如果结构体层的校验存在的话,需要进行调用.(这边是规则类校验) - if cs.fn != nil { - cs.fn(v, &StructLevel{v: v, TopStruct: topStruct, CurrentStruct: current, errPrefix: errPrefix, nsPrefix: nsPrefix, errs: errs}) - } -} - -// traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options -func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, partial bool, exclude bool, includeExclude map[string]struct{}, cs *cStruct, cf *cField, ct *cTag) { - - //read note 处理Ptr、Interface、Invalid(validator自定义)、自定义结构体类型. - // 返回参数为:值 、 数据源类型、nullable(用来校验 【结构体】的【omiEmpty】标签...) - current, kind, nullable := v.extractTypeInternal(current, false) - var typ reflect.Type - - switch kind { - //read note 处理地址、Interface、Invalid是直接往校验错误池中添加一个Field错误? - case reflect.Ptr, reflect.Interface, reflect.Invalid: - - if ct == nil { - return - } - - if ct.typeof == typeOmitEmpty { - return - } - - if ct.hasTag { - - ns := errPrefix + cf.Name - - //read note 如果是Invalid,需要往校验错误池中添加一个Field错误 - if kind == reflect.Invalid { - errs[ns] = &FieldError{ - FieldNamespace: ns, - NameNamespace: nsPrefix + cf.AltName, - Name: cf.AltName, - Field: cf.Name, - Tag: ct.aliasTag, - ActualTag: ct.tag, - Param: ct.param, - Kind: kind, - } - return - } - - errs[ns] = &FieldError{ - FieldNamespace: ns, - NameNamespace: nsPrefix + cf.AltName, - Name: cf.AltName, - Field: cf.Name, - Tag: ct.aliasTag, - ActualTag: ct.tag, - Param: ct.param, - Value: current.Interface(), - Kind: kind, - Type: current.Type(), - } - - return - } - - case reflect.Struct: - typ = current.Type() - - if typ != timeType { - - //read note 对于结构体,这边有一个比较特殊的处理就是cTag是从第二个位置开始,也就是之前一直尝试structonly不成功,就是需要在structonly前面加一个tag才行。 - // 前一个对于struct应该是不生效才对,第二个才会对struct生效 - if ct != nil { - ct = ct.next - } - - if ct != nil && ct.typeof == typeNoStructLevel { - return - } - - //read note 如果上面的cTag没有生效/没有tagType为【typeNoStructLevel】的标签.就直接进入这个结构体 - v.tranverseStruct(topStruct, current, current, errPrefix+cf.Name+namespaceSeparator, nsPrefix+cf.AltName+namespaceSeparator, errs, false, partial, exclude, includeExclude, cs, ct) - return - } - } - - if !ct.hasTag { - return - } - - typ = current.Type() - - //read note 进行字段Field的校验,这边的话是一个for的循环,在不同的标签中去找到对应的处理方式 -OUTER: - for { - if ct == nil { - return - } - - switch ct.typeof { - - case typeExists: - ct = ct.next - continue - - case typeOmitEmpty: - - if !nullable && !HasValue(v, topStruct, currentStruct, current, typ, kind, blank) { - return - } - - ct = ct.next - continue - - case typeDive: - - ct = ct.next - - // traverse slice or map here - // or panic ;) - switch kind { - //read note 【dive】标签处理Slice 和 Array:往数组中的每一个元素进行处理 - case reflect.Slice, reflect.Array: - - for i := 0; i < current.Len(); i++ { - v.traverseField(topStruct, currentStruct, current.Index(i), errPrefix, nsPrefix, errs, partial, exclude, includeExclude, cs, &cField{Name: fmt.Sprintf(arrayIndexFieldName, cf.Name, i), AltName: fmt.Sprintf(arrayIndexFieldName, cf.AltName, i)}, ct) - } - //read note 【dive】标签处理 Map:往Map中的每一个元素进行处理 - case reflect.Map: - for _, key := range current.MapKeys() { - v.traverseField(topStruct, currentStruct, current.MapIndex(key), errPrefix, nsPrefix, errs, partial, exclude, includeExclude, cs, &cField{Name: fmt.Sprintf(mapIndexFieldName, cf.Name, key.Interface()), AltName: fmt.Sprintf(mapIndexFieldName, cf.AltName, key.Interface())}, ct) - } - //read note 【div】只能标注在 Slice 、 Map 、Array 上,不然就是报错. - default: - // throw error, if not a slice or map then should not have gotten here - // bad dive tag - panic("dive error! can't dive on a non slice or map") - } - - return - - case typeOr: - - //read note 【|】的处理 - errTag := blank - - for { - - //read note 如果结果是true的话,因为【|】标签只要有一个成立就可以,所以可以直接排除掉其他 【|】标签了 - if ct.fn(v, topStruct, currentStruct, current, typ, kind, ct.param) { - - // drain rest of the 'or' values, then continue or leave - //read note 排除其他 【|】标签,直到下一个Field的非【|】标签再进入处理. - for { - - ct = ct.next - - if ct == nil { - return - } - - if ct.typeof != typeOr { - continue OUTER - } - } - } - - errTag += orSeparator + ct.tag - - //read note 没有下一个cTag的处理器.处理一i西安错误信息,返回. - if ct.next == nil { - // if we get here, no valid 'or' value and no more tags - - ns := errPrefix + cf.Name - - if ct.hasAlias { - errs[ns] = &FieldError{ - FieldNamespace: ns, - NameNamespace: nsPrefix + cf.AltName, - Name: cf.AltName, - Field: cf.Name, - Tag: ct.aliasTag, - ActualTag: ct.actualAliasTag, - Value: current.Interface(), - Type: typ, - Kind: kind, - } - } else { - errs[errPrefix+cf.Name] = &FieldError{ - FieldNamespace: ns, - NameNamespace: nsPrefix + cf.AltName, - Name: cf.AltName, - Field: cf.Name, - Tag: errTag[1:], - ActualTag: errTag[1:], - Value: current.Interface(), - Type: typ, - Kind: kind, - } - } - - return - } - - ct = ct.next - } - - default: - //read note 剩下的标签处理.类似一个循环的处理 - if !ct.fn(v, topStruct, currentStruct, current, typ, kind, ct.param) { - - ns := errPrefix + cf.Name - - errs[ns] = &FieldError{ - FieldNamespace: ns, - NameNamespace: nsPrefix + cf.AltName, - Name: cf.AltName, - Field: cf.Name, - Tag: ct.aliasTag, - ActualTag: ct.tag, - Value: current.Interface(), - Param: ct.param, - Type: typ, - Kind: kind, - } - - return - - } - - ct = ct.next - } - } -} diff --git a/SourceAnalysisAndTool/validator.v8/testValidator/Data.go b/SourceAnalysisAndTool/validator.v8/testValidator/Data.go deleted file mode 100644 index 57bcb23..0000000 --- a/SourceAnalysisAndTool/validator.v8/testValidator/Data.go +++ /dev/null @@ -1,33 +0,0 @@ -/* - * @Author : huangzj - * @Time : 2020/12/11 16:16 - * @Description: - */ - -package testValidator - -type Ower struct { - Age int `validate:"min=10"` -} - -type Cat struct { - Age int `validate:"min=10"` - Ower Ower -} - -type Man struct { - Name string `validate:"ipe"` -} - -type Woman struct { - Name string `validate:"diy=5"` -} - -type Person struct { - Name string - M map[string]int `validate:"min=10"` - H int `validate:"max=20"` - Exist bool `validate:"exists"` - Require bool `validate:"required"` - Cat Cat -} diff --git a/SourceAnalysisAndTool/validator.v8/testValidator/Validator_test.go b/SourceAnalysisAndTool/validator.v8/testValidator/Validator_test.go deleted file mode 100644 index d6a98bc..0000000 --- a/SourceAnalysisAndTool/validator.v8/testValidator/Validator_test.go +++ /dev/null @@ -1,158 +0,0 @@ -/* - * @Author : huangzj - * @Time : 2020/12/11 16:16 - * @Description: - */ - -package testValidator - -import ( - "Go-Tool/SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8" - "fmt" - "reflect" - "strconv" - "strings" - "testing" -) - -func TestValidator(t *testing.T) { - fmt.Println("测试别名校验器") - testAlias() - - fmt.Println() - fmt.Println("测试默认和自定义tag校验器") - testTag() - - fmt.Println() - fmt.Println("测试字段校验器") - testField() - - fmt.Println() - fmt.Println("测试结构体校验器") - testStruct() - -} - -func testStruct() { - //添加结构体校验,对结构体进行处理之后,validator的标签还是会起作用 - config := &validator.Config{ - TagName: "validate", - } - valid := validator.New(config) - valid.RegisterStructValidation(func(v *validator.Validate, structLevel *validator.StructLevel) { - c := structLevel.CurrentStruct.Interface().(Cat) - if c.Age < 100 { - fmt.Println("猫的岁数不能小于100") - } - }, Cat{}) - p := Person{ - Name: "192.168.0.1", - M: map[string]int{"A": 1}, - H: 2000, - Exist: false, - Require: false, - Cat: Cat{ - Age: 0, - Ower: Ower{}, - }, - } - - err := valid.Struct(p) - fmt.Println(err) -} - -func testField() { - //如果注册了对应的Field,则会调用自定义的方法,不会再使用validator定义的标签 - //这边测试了结构体和基本类型,都是如上述描述的这么处理 - config := &validator.Config{ - TagName: "validate", - } - valid := validator.New(config) - valid.RegisterAliasValidation("ipe", "ip|ipv4|ipv6") - - valid.RegisterCustomTypeFunc(func(field reflect.Value) interface{} { - d := field.Interface().(Cat) - if d.Age < 50 { - fmt.Println("狗的岁数不能小于50") - } - return field - }, Cat{}) - - p := Person{ - Name: "192.168.0.1", - M: map[string]int{"A": 1}, - H: 2000, - Exist: false, - Require: false, - Cat: Cat{ - Age: 0, - Ower: Ower{}, - }, - } - err := valid.Struct(p) - fmt.Println(err) - - valid.RegisterCustomTypeFunc(func(field reflect.Value) interface{} { - d := field.Interface().(int) - if d != 10 { - fmt.Println("测试一下") - } - return field - }, 1) - - err1 := valid.Struct(p) - fmt.Println(err1) - -} - -func testTag() { - w := Woman{ - Name: "my name is Woman", - } - - w1 := Woman{ - Name: "my name is wo-man", - } - - config := &validator.Config{ - TagName: "validate", - } - valid := validator.New(config) - _ = valid.RegisterValidation("diy", func(v *validator.Validate, topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldtype reflect.Type, fieldKind reflect.Kind, param string) bool { - s := field.Interface().(string) - - i, _ := strconv.ParseInt(param, 0, 64) - if int64(len(s)) < i || strings.Contains(s, "Woman") { - fmt.Println("校验一下") - return false - } - return true - }) - - err := valid.Struct(w) - fmt.Println(err) - - err1 := valid.Struct(w1) - fmt.Println(err1) -} - -func testAlias() { - m := Man{ - Name: "192.168.0.1", - } - - m1 := Man{ - Name: "213123123", - } - - config := &validator.Config{ - TagName: "validate", - } - valid := validator.New(config) - valid.RegisterAliasValidation("ipe", "ip|ipv4|ipv6") - err := valid.Struct(m) - fmt.Println(err) - - err1 := valid.Struct(m1) - fmt.Println(err1) -} diff --git a/readme.md b/readme.md index d6a9e43..e549450 100644 --- a/readme.md +++ b/readme.md @@ -62,10 +62,6 @@ 2020/12/7 :更新bit位操作工作 BitTool -2020/12/7 :添加container包使用示例和源码分析 - -2020/12/14:添加validator.v8源码解析和使用示例 - 2020/12/15:添加前缀树工具,实现前缀搜索和字符串搜索功能 2020/12/16: 添加YAML和结构体转换工具 @@ -79,6 +75,8 @@ 2020/12/31: 修改diliver包结构 +2020/12/31:删除源码学习部分,挪到Go-Study工程 + # mod vendor模式加载包 通过go mod的方式加载的github上面的包会有报红的问题,但是包本身是可以运行的,这样就是会有一个问题,如果你想要点击去看方法的内容,没办法做到