From eb50b6273b7a03143615782ed121aef09b44a2d3 Mon Sep 17 00:00:00 2001 From: Huangzj Date: Thu, 31 Dec 2020 16:49:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(Go-Tool)=EF=BC=9A=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=202020/12/31=EF=BC=9A=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=BA=90=E7=A0=81=E5=AD=A6=E4=B9=A0=E9=83=A8=E5=88=86=EF=BC=8C?= =?UTF-8?q?=E6=8C=AA=E5=88=B0Go-Study=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jdkContainer/sourceAnalysis/heap.go | 157 -- .../jdkContainer/sourceAnalysis/list.go | 255 --- .../jdkContainer/sourceAnalysis/ring.go | 150 -- .../jdkContainer/testContainer/HeapTool.go | 36 - .../jdkContainer/testContainer/heap_test.go | 62 - .../jdkContainer/testContainer/list_test.go | 69 - .../jdkContainer/testContainer/ring_test.go | 114 -- .../validator.v8/2、结构体缓存获取.jpg | Bin 220247 -> 0 bytes SourceAnalysisAndTool/validator.v8/readme.md | 5 - .../go-playground/validator.v8/.gitignore | 29 - .../go-playground/validator.v8/LICENSE | 22 - .../go-playground/validator.v8/README.md | 366 ----- .../go-playground/validator.v8/baked_in.go | 1429 ----------------- .../go-playground/validator.v8/cache.go | 285 ---- .../go-playground/validator.v8/doc.go | 852 ---------- .../go-playground/validator.v8/logo.png | Bin 13443 -> 0 bytes .../go-playground/validator.v8/regexes.go | 59 - .../go-playground/validator.v8/util.go | 253 --- .../go-playground/validator.v8/validator.go | 829 ---------- .../validator.v8/testValidator/Data.go | 33 - .../testValidator/Validator_test.go | 158 -- readme.md | 6 +- 22 files changed, 2 insertions(+), 5167 deletions(-) delete mode 100644 SourceAnalysisAndTool/jdkContainer/sourceAnalysis/heap.go delete mode 100644 SourceAnalysisAndTool/jdkContainer/sourceAnalysis/list.go delete mode 100644 SourceAnalysisAndTool/jdkContainer/sourceAnalysis/ring.go delete mode 100644 SourceAnalysisAndTool/jdkContainer/testContainer/HeapTool.go delete mode 100644 SourceAnalysisAndTool/jdkContainer/testContainer/heap_test.go delete mode 100644 SourceAnalysisAndTool/jdkContainer/testContainer/list_test.go delete mode 100644 SourceAnalysisAndTool/jdkContainer/testContainer/ring_test.go delete mode 100644 SourceAnalysisAndTool/validator.v8/2、结构体缓存获取.jpg delete mode 100644 SourceAnalysisAndTool/validator.v8/readme.md delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/.gitignore delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/LICENSE delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/README.md delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/baked_in.go delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/cache.go delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/doc.go delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/logo.png delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/regexes.go delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/util.go delete mode 100644 SourceAnalysisAndTool/validator.v8/sourceAnalysis/gopkg.in/go-playground/validator.v8/validator.go delete mode 100644 SourceAnalysisAndTool/validator.v8/testValidator/Data.go delete mode 100644 SourceAnalysisAndTool/validator.v8/testValidator/Validator_test.go 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 8eadd1a50f029bcff7455e89ffa425b83a15eba6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220247 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ν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

lM0EZ^goi**`7z#YCj6a@Ox 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[![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 355000f5247d50e979cf5db5de38188ef4649a34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13443 zcmbVz^LHiB^LK39wrv|5-`KWoTN~T9%?&s9Mte8f*xWeZ`~Lg^&kxU>)6-|>Om|IH zcUM=vsybFxSr!?A009gP3|U@IN*z>Z{#W2&KzAW<*L_e0I`lYd#@osT8GH952<>}$=#%H%txCM^!YLYIPG*~?*PoX}XfpXD#$r$vg% zUJ@M8Sa6}E0bs?J()q&Aj2!Xx^!*X7wf45!j09TZ!t8tmiZrhYa~rM!hkOgG3jNOL z$t%hsiEZp{`uZS=pUq3db%5@e>LpqUR%RzF4Fp&XYtszH3NMj(x&yBfN!B@dDe(i*$ zFaI9z`VK(*+SzZ3Km$V|gFS(NfPUS&ND}#zKM&MsZR;zy@SJwDwy5moK{eH84yz0`{Dhd+jynpps_Wzr*Rl)ctU%7jk!=>D(g}(sK zP}YV(B1|d_4NeR~4qlx?36qk5ng9u-wt+@fOTlvqhk>WQ%HxtjxBspSS(-6OpP;_x z73LX72W9oA=yUj&B*sjt0z}2U44ACNztdo!tbwR&pl8vCLjf!@HDwcP;p{h$JYsrk zE3Pp7L^A>!xwNPSX+2zrQgJ8|CCr11n`u|=C}{? zlHLN%{DxBD;+;&!6Se$BciUB@EQ~Y8_ZT-Q&4p}|A3l`R=AVR9Kt+V~a3a3V{l=)gHBK2op+X}BW7o(X1K2eRTZ^; ziO?#OmuWkXeCj2*{H(1C#qnQ>tz|Kq>*#cF7g)+?3G3(pVB@N37)9YHmYxa}CVb-% z@SHf5CnrEMiI6-&fkkOb9ema$%-Ld}qN54xNf|CDt?#e@Aec&IEcEEpu3Ak5Y z>0@s)b7yHEr~UCsek0JVuF%66MBgBxj-d!wQu4Evlx;p|pZG{&=4VV)*pIE{{f=SO z;V$)QC5ae=-6(Nc68{(S;2ymNVxIiwAs9}A@vA2?55kfV(qK>S6caF|bywd&p8ydL zB}xJ~6Di7u^Xl{s1E&b!{FXH0#>1$=MTNA7+vd;Pm*#B`iYRecX>5H7^iqDqQ{GQH zKNNh0?p}h?nEjh_Ft*^M`+(a;L*rKgPp=E!!}stvVxG|YKY=Yh25?+RloCoyT3T~2 zr1!?YL58}YTlyj1sTl_H(oBl48zJPwJFr9|r(>T7Npe$Hyl7Pm(dZ}|x;n!X(4wtZ zeNCCz4LTygy(gl;pV;dp+-Lpq=weiOW2Z_Lt@RNd_s43tZ>$@23^%6`T}rfexq!%# z)e|oR;kRY~2fW@V(in6QZzE*6TubN0<>|v2xiX)v6->d$no+&np8 z=DZPj>yPVL2Y2U^MJuW`R8R{2@Rg&}`S+$yEgsGihuW$3 z2y*A5Rm-TCh*xaY#R1q)HfzQS_%fPHCL7200}u=S#u`m zvW%z6F_UcmBq~g~s|d}v6$Q?noL`Z(X;@Q$i>kw^bF}I3A8QQyAE_nz-`H~a9o2}- ztPUs0q(DTZ^Yx3oA6C5I?{nHCX0qfW&C2r}h~~slhe!$_Hh1WB`w?_|D{JsF#zpgf z;F^yDTZs-$?`myzyDj@=x}@L4b~_KtUWzV+uiL${48Qh^ZdoywlRNR<*WLFY>v0fq zeWQS`g6{8q<#x){FrCbZlcTAh?+fw^gB-2LpRnlF^}`$D;(KxTOLn;dXs3Yl(uW$g6hyw3{wZdTVg|kdSet`n+SACG=!&%#r zl+Ha_MzD$G>iQb%tW~Uus7-zOMPI__Qo92dK3VKkGgR#;-!`uw++~l5J?MT+BUCv3 zcItfZO)uKXlipj1XD?F|>3frjQWA;$JV>TcHHrcrR=Ql;-B}Bb4;f|uVo(S7xL(QP zE%c8{bnchCJ%aG)3x8gx0`Hqq`eapfWqK`~Ec6Mea`v0{J?4~x(S2D#-7sMBR1X;{ zO-QlMUsyD!#jI^8v6y2J8TinHz_zsU@;3|?TfT0F2b2A7aX&aEQGc;IZ>UV*cToht z27rX9TA$h1ZMxk`KX|$6o$)=$PxIM3k^FhGmiJMaA3fBM6(M#efLJ9ucfbo2TkroP zxE4Dv?B_Nkef;0LYVj3nk|C9-MLv{y^-tY`SD(5phR2KMn}9@?I@SQ^#m* zu>9T8l>)311+yf)qc`Zp%3Cp9FS4PN18t5zZGy-!{f^5eJQA&Fb>Llf4kF^OZ}Tu z=jyadHyzlQLaf@_eAf{CFb}_v=Gj*BLc$VrMAe%hAL@6JaXkt^p&>`#SXjBAX!3#; zZ(sPdwtkoS08=HP@lruhHm*fIlu{y~LTu@+@;u*LBUU~nbQ7S{eH09xc5^_Xtu!q@ z6^P#P!A-(qwW30Th;TBWNp{b1+lP1D!2Y2In`HJ8=DTs8;1)Y~TE2Tco&agHaJGJRtE&{R2y^@Gnpny|$qxXc2=Ps$@$~9mxET{1Q$%i!i#frlzo0UOe_Y zMxNvLk98G99Jhl+-rMB_{OyQsE?70nTDUTZf%>P_;7WAz0a+FG*4EALUD*p3UWt_( z3yZrIM%L#2dleC=K}bD*)-@4195ctqtgM0iQACxJ?F&0O<{t?%^dK1pMJo*-dHj;E z%Vt=-^pa?Z(eb%_rx~$m@yuyvX^t!IvZZ&&LJtY`#;x+PXT-Gb~(3>gv;tf~4N37#aCX z-tW%A@AM^Cf&WBJl*|wp9s0RGq_rCL)=Klfe3e8BUY|7FGZM)#ZdT04zyZ#{*|<&8 z+dsxt9B+krqDfJbykPO==|6C|yAi)*jkV&C{Du7Y#drV0`{jGeFSFOANIz#B-ncz= zB?v}IR2j5eCJ`2>yNMN9<}h!(e$i><|KSPd(Ff^lC-7pg&G~QJ8T0JD-37gq1-K+V z;1?GW_CVrGX3V0m%yvW#+uGLl^01=9zyGrgZ5fJ6GeeULS25^4)YCL=-Z!w`r$tH= zj-ikdG|nI;y1wvvk2)h7^hL0Xvnxw)Y1u}&9Vv%k1};Z0IqW?AQ8)B@QOUa?ayt31 zX^`u?pa(0F6YpbrT;e2^auw#%0BX_ub?}_ieYF;4rGRd*1_vX-+Xv9I&yR@ zZF(3;`kXg0vHdTn$5Ie;gpS4@djPPJ60-Z_1?!DwQz9NO2jKDbkZ^oJbQVc?6v#&0 zAW|kWVx3>tw#eTFT> z$S^|&ZWo)7Lyes7r)@VL=2A|$JW1nr)ed9~F&(_uHC1f;YO_5oj&Afj!0(9M)7c*f z$rra8Ji?1Bc%e|v^CcS{(B7RRCc7Wrrs=I7)f#8IE{rDM)o~`?Y8!;pSaL!lLHCZ% z2RHV1+l?QSk}_AkH)`_s#(xKJ?jwKC`csy*aOGtV&`hmHIG<5hXtzm+=iQkb{pyZ< z%;RxAP~z<%lTo;vNWd4mn;*jW+1tVM*tJ0j)}5|LR4#M7r{PkXJaW;yHBr@9pIuiG z8V1M4Ci1&Z6T1I>(C@#6rJT=}4_MR%kp=0LFD)iInpDCFQ;rm ziA+yF-c%|NyQ8);!vM6)#xu8qylq9(nieBl!@e}S5}R@)8LEU)Q|o0z)Z3vP);l2n zvCG7gtlR2XtjF1}fhC?!r{BZ4#sNRJi-Kgt?Rd(rePR;wmE}rqM-z^#fA_=ptrRR~ zqS-A)prf=s19gdfPBn?#&j;!a+e1!wX7|RMt|@0KQ_^z7My)2imN}+? z&Ro$-#EC#FN(11}WJ|$X)eQ0hf7Xye3AhvowX$0|1+x+uY~g?ccTKswq+io;vFNd6 zr7#C9z4;>@b-tg$UzV@9U5hK{mDW{6%YjDa>FJu9Z8hZyN}pshPN=W>uI!^Q$kMqm z+}IiQA9sdYvoB1IiBfX#m0axM;6c8}N>K$tD8kW56>r1h5t8J!3X0YAj1|Aw&~l@A zxf2^V`F;A0W?i!7*yQ+#;?4!!1ZQrBEI$9+-N z6P_sTrV&}s7MX}77Nq}~KmQy&5T&0ZWX--y(<$MEOLGIm!7k)jQOWggN0!Rg^`Bj3z7;;PquhhFnoqJeAbUfHR~d2;C{_De_Ogp81i65*qU(X5fweyv+B#w>RW0 zm&_w7Zm z`YWfGxm^7MK^A>0nDITy;gz^Lzudv@BC>+^JOVExD%|?aa0W#9qe``&CHjF6vqV zB8&tSqdhz{r4(|w3!g-DZKg>^k=!a74kk`D{P(2>&R~8kXP)^Ns3jTlnM7|b=I@?W z*3YW^eW^H83@t)lUE4LAm#(ICbAZTgW?ohHU;Ok91QJvMGp6fHL|&TQb|ICaXi{OO zrD__`B5>e)a6orX^!P5CsJZqQhI9-E6v4*!cC1vUi2?G|44quG+rfLS+7ZX;meFoT zMa+fb0pH+x{|o<7L^;cM5J4}K*7m~l#N2_qa(YL%G9rt7(fo;z(CaJOODkCKPA9`Bop?dIYFl3wBU&l zdqN~tz4k#i1&+HT_N>0Qm%uxG;}xqfaciIXXK|67VNTu0yzMz6pt6)m~ z7y^EZ+(wMlK9yMiwkhp&>cmXQoRzGf`o{MmkrGaxJY*%s0Dza_WczOvC8IXtY4zGE zoAfaSy~MQoF^;l5RWb}DJq*S_&wp|_lkCAaR~iQkooeXo>yX+1hRw(?%#&k0 zm|IG1?>%mpBmLr(*DC>|Vr>bN;nKsdZLlS4*_h%G1n`;;6|sE0rg^T9KG)Swoz!z& zJra776~H1@daS@C;jzI*0~;x5(E1Fpo!nLAV=SmM;Q>*#bxdaC<;wO{!IV4ONwN}f z8NK=|T>UjQ5%%_C3KAVb1}wC~Feno-GH|l>&?HI*RX~t*0XtJ~S0R6Kst$kD*7mw& z{mR31-KopNO5bKJqku0*PjnBKFE_1y_|tmDtiN7SF!NZpwNb5#sV6w^bu9#1B5K7# z0N}))422cqc#^(uW?wJU*^KLe?VU&(*c6j;U6^LZcQoK4POU1{yKSH^?k2$VGLEWB zog!7!3_Kl%apr)=%d3Rpw_4BDLZf!1tIdN&D;Yg?X2&jp0vSBqbz)XX`Wu2%`IWJS1s3lhZ7H--?PJxQLg$XONw$8qE z@4G(S5}8yFwM`{Rdz9E__ZH{{Gusj%$t#w4+ac&G3wkM0n&qZPP}J9r*av-Zq- z%NdhH1sgs~Oq9{PLkkxDiK6MQo36OTZrr&F7k6+F*a}5hV<;1u+B`QQSF#ti5`pI3 z@gvRFovLjNAri8~54co-plD$yQSX*b95r9t@B%~eI2r9NqXw{mGRKtdG5*|wk~yO zW)?msL*Rlpy{X4OLKx;RTX5`t1RY4!(bJ`a7rJ?=xM7fwcCL;k7j%-*cj9NLfbojM= zsFk;>hWcz(m*MFBO66YXrs>D4!BqdqWy_oZ>c&}P@|L*1a zVk(-?<3wy?;t9XLM*dyTj^XbicaVIM%BJouomO8jaqzV51LbTf>Ywq=#cXFtO*-oC z$O(ezf}G*);p^d{5Cc9apUxWE7RHp-F$ne9h?~C!5ok6%glp3JFOLJd2A-Fm@I}Id-s z30mMGUBh}2LTd&+z4*b8fB8hNy+ke`kmJbFXYm9=Ud96znCvs;Xa*GB`{*jEPp($~+DX+RP*)$prD03Z~ zot>}r&YE}7>5Wkie5E(*NC^ihU`EdF6Ezw%Y_=C72{{2}2gipm z*Kp)Aa`c2J&xYYZ876z^z{Zt5pR2|?72(fT&g8MYt4OgJ8>+ZDr_oB=>9xhEw%27Y zdZWI$a9GrD@5Los+iFbyl507c-TMRH3x)MMT{uczOKy3!ra7;z>2})#CRqJW`Jr@s z)uA36KCgr8c)q);G>N2B3p4kyV4NWuoxzls;Xqq+eg~fI$A3otuea;KAQGd#L@`_H zA12vy0BVLhln8XMstlX5M43pjjcZzAO3GUc$zV-2^wq;7JE(EwPLoa!*2(XgxwSlx z2_J0xvN3`hnHWW^kuO7z`%AW8B~t4yhgSPHzS%y%$=}V7s+fZJ0#{k0^O+*L0|Zg4 zfX#xMrgl!s6Xo=iNk_&jq83fy!YAvDSuT8GO6%m58Pi*2YUR|;TQb;TdN=rqTpKIZ z-p&;$N{lIA6N##--%mV~CtEEa4=)@J`4YoT@$9}xH&qcX>lvW>wj*s%n1(JbS$r*d zK9ca~LMdTQ7v!Y34Q6Zh;50&tLX-E@$j3m@9%{iLEyrjeeM_lyMFuI6_pPMcUemdp z%6;iM!PP84B5GQ70B|+R^|BqipYC7_%BZRXP;eo#KZ6EBvBzlpn}@P3p}|8#I(4 zul0x<>TxI(s0g?8v|a89+n1)Jx##kH*g@FY*niUw?{Sqmm)Xi-;WBKlUieBT&& zR3bfdZ|yI{!e~+H2q@uF@=N3k*$H|RZpj@5hvmw~_Py+wV14-k8ynOVi-{@1gB;!g zop(C8F2W!)$gD|@VYtF3M2`gl44ny?45baF7yCBl4PB@{E_nNFz6{2b zr3nxXdd~S*FLLzzO#wytqw(3PI0_%D56fEkMQPca=JX$gqH9aJ{ZpKvk8&kz zVxpVpl56nj^P5R4Lm_KK_6WeFW0cD?IY zZu%H?$YfA5eBYF>2g^}+ig>LD^PgW_C#jRJ$|LNXlubK_b)pT9uqy)nlg?;4DG*(P@1w56aN4^TZM6bWUyCM1*1Czy}HIA#1w25=*y73 z^<0dmnQg(qFmL~t3lPYXx1H8~Zxg@d(x{4t40F=4{->PSRp{RzUszJHDlXejc7G)lY;8~fKsU-hk(590&9v& zFxr}ZKJqco?V2qb5bnkeLoQVbyu32=?$Kwh?;N0OiGN|7=6`RkdoJ(JT@djZ8dUCb za?z#~&v8Fm?V}L${Zr&aQ8JC0EF>X56u4pkjt-w^+1bG$r9f1OrJ$<6qE&iV7_}kN zQweT&?sbJOanV*#E0|bLjkCC(vOm|{V<5MsimhiSt-uxzjxz9SMUvMQK{`~RZ+v_m ztb%l8kCZHm@?oa?Mb$L;Bv2$(K*V=w5SD>$*ITQ!W*n%SOXJlQO>pLoRxLI#%aHpA zmYUE<8T)d$P6F=j$+`7W&dSV^FR;c5cvU=igm6$Q0Bz?EE|?msF@JEX89DoMOUuTr z`R{3)%|h-VtA7`wTgs8)s;PQ6$6IvQTsUzrO=Y6G!D)=Xx9w0$Gba6n1y?{dK@SoK ze54vzFH|9D2~QbpUTb_H)IYDfa|J}Lq9?%CFHbsIB8(vc1WUKbA`4uL=6b&iurle2 zi(4jg{2hA5K*7uKNnBA0KV4x*3NO0jb^QuEWV&39?%#Ve9aEQ)AWUUwycBSf_o%|` zTcm^fRU(B}U8I(N*#z&8fsGAkKpBAt5@UnRa>N{07@%qaw@bs$K2R5VP#c$2^Q%RQ zVuW0slT(*~U8kk?duR;_jOTpmwrrbx->n}JX^_|@zO|a)Ik@>X7HOQ(!z(#CF@`^7JGf2aEfn1S0v}oHKo%uVUMDjl3<>f#kD$hfw(^nW(aRB6AaG-TDAh%oHjEJ=J$;2s zNEtTUsuZa{ji(_8)1j8gUOb~B9fXBSc)M%Hfsu<`&aJGt{{#rePUQ zno1K;1#~H`?Rd#V$}MtvkS~UOgsP~@^u^u{ua{D3V=Fa{2IKwI7>|!cOUteP#X!Z_ z0=9Z(Y!#lhZpJ0TKxMl6%R?6~lt!EvNztb>dbADO5-ZkYS1f(TlqF6|c^Euh&Dojz z>7lTs0ClkTp5>|*~0 z_E{QdSna;}KOcu@*xbF3xyhffB&XIT`p{6hS*F))v#>=YEtJB9Cr*b2YtK$qd9@hS zP$+_%N43)URxgAF_fx!4#yRV$Y6W06mtQ<`6RwW>A*AaHVyEylR` z2)a@71;tKHeL9Ik*CB!~)Qw;=Fl6gGLG;?;LTeerep>@XsgVh4FN73z`?Z=yj9;v% zBxr{}l;h6)J_enD_Xs$w_!zAMpK(;B2{L7;9924=)DeQQG^=eR>S_sq&5Q6tF?!ZR z5Qknd!5HirCsnTIK}aSQLQ_)EQtb#JSG@QUVD}mpOr(idOXutsza|QP5K1WjdsWrs zkY855Sph`j8nzw^f)v# zwC?)Bwo9-}lWq~G9ow>)3->q?FnXQ<$)Y*Vq?hu8MmH8aL1yGrPXCBBQZxc2c}gM_ zazx&=nWtc(!DSU&y7M>VVWHK|f42Z4$ zgM>V`3TB$s+ZXAeFq65x>B{Mdc~^YySq_px;%mpmr2Huz$C}=8-KJN$50%RxgBJ`5 zP&~~O#I1B_1NXRe11=!ZG+8?m1fW)N1v3M~LuJCB_sLZ){E+CtNyJ{zEW!m2t6~4F z%H681*4phFkdH+Wb0LC&2rz`YF05QDpj#b^CS9c1iNN6yizQhsjIRb7ouDlN!>cKa zg7n0;K8z}XHxXi2Ecua32b&VylFo$*L~5$eud(~1>99o0y8R!-= zN_$<&9xytjEu>6segSMd2}6=@3VVB@GhvK>e5(3kr&=sV&}-F69b-m9?Ip^S&_1rK z)REQFT(LR2P6B9EqR$$Fjhw z@@PRbM9s{1I>jgtQ$A{Too_2xnL(GQD!IAjpSUUis4yB{sY$2}MT}d+!IfS_pu32*B z(%fM}`E)&K1vl5$L@*MaDwYf>96D4c;kb|PKTS;+YgrY9Ko@0Q)3$VlDZzF2D5qzp z3ooIC#iZNaZ8P4)aA|hlnC{a}TPrb~vTu2a+lFss)C;W1zZ926mndG{GXR|B)WfV} z(w*ugyn0Rs7_}^z1)X+M+)NXwrEUSMFwNFX_HD7RuV z!p-X54t?QhInx8)RxXg9Gk>_MaF-=XqAoa3dpy^>ZnMr+Cdt={MR4L zlI?2b=gsG3&Ijqpwy~pkv)Y=9n_|E|4ghMbhOV!U-CR;Kg+YdeFwVdfiyc*SZ33P= z$^Lo3LKgdGzEro#sbQm;1h}cbE=gD;VPV$RSAC(NX#P3$r*wNcQV1ac_8s?7<*v7Pd5{UE zcj<@b8s(}ugB+l6X(Y2RciZYZr@$lnh&EYVD&Q;@IV#m~)&N`>i%eC8QGg&uMXI=s zQLp~@6So9V;*{|ZngyWwRLWwzOCrXEh&`MazZ2wm)kNAKFDMMTX_jGA!oO_hJ-YRa z$^tLI^PHPVUu(o9eNPBKBkY8oY*JvIpawcN$Hq>rF`BD0kq%ngOwjI!^ei&^{U1>= z!^&Yoa|y-vSLjPKIP(7C?$zHcE6TomiB6zAM~x|S=v76w%>=hQ$rVordZSPGH_r!u za~NE4L)9W;Zi;ur8=N=;g2x`9ew-T?zd44CWDowkmcCKC2ZEkwyy{Cgf?DBwA)VTz zfJ;~J*q-_{>l2=#Z#w%BHa5yiZUb#89mRN|$!s*X41Sj}m@%Y%D8!j#oex}HpuLkT zi_70a875WHbj(&5q=Cb3*-Fn-b_=@DxVxh?M%~C#aO%I9A zfDhFlS)5h5m^sgc`qgo&LB;4CbJ+4Do$EQJL-i45cQ|%b4D${*iHS6$Z!lFja4{Z& zm_cQ;+$jmX_Ipjb?|qoQbz3TEQd@UgHO-t8i&2#uH*%Y+@t8HptKD;^>9mRb|w53r?9PIIfP$v|io_ z*cIdNpF96_?%r4O-CUdtgPsVgQ7~>`(Iv=~Vz&=N0I0@6UyQtkp156a;eRI#QPSg> zAcDjr+gD33>K!@@N;gSJr1%xowp?n{?=lK{fWo0V0xrMs(WD=)!hLrQ-FS z@!mYs_Wz~@&+paJijML41V^ce^;23KtbY_xNJKz@7&zTeFEoHm7;$(UI=YQFs#$@ptk!EQ42Y4FfxEf@TOsVt37 z}4AVbnC9Ri){mLjd@o@_vA;wzpV8G_ypN3Y=M08M6ZfM2Xtkpu^=A9}u!A?A z)0NYU%Y#TSSE#tnm?KTmo4 zd|UY(Tqjl;m?`7^R${$QG*ZIW=)p?(%lWYXyf8k9{rdP=)z$ty1cAPSJfgXTOPXN1 z^D-Pknjk$jWsP@0+o&sn#8=lA=)a-i-j|YE5DwZ9s#vk3w-c?}%C?C;Q@<(1;-i>L zl}SN#MAX*71GGR14&RiPaHe@3srrMMPYHjml+|aGSDU_fRi{h1_NlT;MHYR@D(IR3 zt6;N#m)Tdz?)V=$7s!&Z;ZdmJFd0m>InR~Umqz^)eM=coLx(q4tw%~Z0U73ho^=Mj zF)fREGIOlh6`*ARYk?K%ir!a_Yvw9snW){J#zyP<3!#qD8Q_2~d|so+(Xc54smil}_4kGqEK^l7mVKQmM+ zBR70H=a2QXGB!3jg`P(Kg~lE^KQr-y_EVJi%}cMMzb+f?)6-|yp{QzpZdk)-9EhXzQpEZ(ZuvkddnL`d4Y{JQ>J+Eg}}BSGkUqgbqYuem+;8++@MM(|;Eh?pTI_O&4Gy6PBOnIB)^cWfo! V^Rh-@K?jDw{}" - 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上面的包会有报红的问题,但是包本身是可以运行的,这样就是会有一个问题,如果你想要点击去看方法的内容,没办法做到