diff --git a/container/garray/garray_z_example_int_test.go b/container/garray/garray_z_example_int_test.go new file mode 100644 index 000000000..c188e962a --- /dev/null +++ b/container/garray/garray_z_example_int_test.go @@ -0,0 +1,709 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package garray_test + +import ( + "fmt" + "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/util/gconv" +) + +func ExampleIntArray_Walk() { + var array garray.IntArray + tables := g.SliceInt{10, 20} + prefix := 99 + array.Append(tables...) + // Add prefix for given table names. + array.Walk(func(value int) int { + return prefix + value + }) + fmt.Println(array.Slice()) + + // Output: + // [109 119] +} + +func ExampleNewIntArray() { + s := garray.NewIntArray() + s.Append(10) + s.Append(20) + s.Append(15) + s.Append(30) + fmt.Println(s.Slice()) + + // Output: + // [10 20 15 30] +} + +func ExampleNewIntArraySize() { + s := garray.NewIntArraySize(3, 5) + s.Set(0, 10) + s.Set(1, 20) + s.Set(2, 15) + s.Set(3, 30) + fmt.Println(s.Slice(), s.Len(), cap(s.Slice())) + + // Output: + // [10 20 15] 3 5 +} + +func ExampleNewIntArrayFrom() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s.Slice(), s.Len(), cap(s.Slice())) + + // Output: + // [10 20 15 30] 4 4 +} + +func ExampleNewIntArrayFromCopy() { + s := garray.NewIntArrayFromCopy(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s.Slice(), s.Len(), cap(s.Slice())) + + // Output: + // [10 20 15 30] 4 4 +} + +func ExampleIntArray_At() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30}) + sAt := s.At(2) + fmt.Println(sAt) + + // Output: + // 15 +} + +func ExampleIntArray_Get() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30}) + sGet, sBool := s.Get(3) + fmt.Println(sGet, sBool) + + // Output: + // 30 true +} + +func ExampleIntArray_Set() { + s := garray.NewIntArraySize(3, 5) + s.Set(0, 10) + s.Set(1, 20) + s.Set(2, 15) + s.Set(3, 30) + fmt.Println(s.Slice()) + + // Output: + // [10 20 15] +} + +func ExampleIntArray_SetArray() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s.Slice()) + + // Output: + // [10 20 15 30] +} + +func ExampleIntArray_Replace() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s.Slice()) + s.Replace(g.SliceInt{12, 13}) + fmt.Println(s.Slice()) + + // Output: + // [10 20 15 30] + // [12 13 15 30] +} + +func ExampleIntArray_Sum() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + a := s.Sum() + fmt.Println(a) + + // Output: + // 75 +} + +func ExampleIntArray_Sort() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + a := s.Sort() + fmt.Println(a) + + // Output: + // [10,15,20,30] +} + +func ExampleIntArray_SortFunc() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.SortFunc(func(v1, v2 int) bool { + //fmt.Println(v1,v2) + return v1 > v2 + }) + fmt.Println(s) + s.SortFunc(func(v1, v2 int) bool { + return v1 < v2 + }) + fmt.Println(s) + + // Output: + // [10,20,15,30] + // [30,20,15,10] + // [10,15,20,30] +} + +func ExampleIntArray_InsertBefore() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + s.InsertBefore(1, 99) + fmt.Println(s.Slice()) + + // Output: + // [10 99 20 15 30] +} + +func ExampleIntArray_InsertAfter() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + s.InsertAfter(1, 99) + fmt.Println(s.Slice()) + + // Output: + // [10 20 99 15 30] +} + +func ExampleIntArray_Remove() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.Remove(1) + fmt.Println(s.Slice()) + + // Output: + // [10,20,15,30] + // [10 15 30] +} + +func ExampleIntArray_RemoveValue() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.RemoveValue(20) + fmt.Println(s.Slice()) + + // Output: + // [10,20,15,30] + // [10 15 30] +} + +func ExampleIntArray_PushLeft() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.PushLeft(96, 97, 98, 99) + fmt.Println(s.Slice()) + + // Output: + // [10,20,15,30] + // [96 97 98 99 10 20 15 30] +} + +func ExampleIntArray_PushRight() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.PushRight(96, 97, 98, 99) + fmt.Println(s.Slice()) + + // Output: + // [10,20,15,30] + // [10 20 15 30 96 97 98 99] +} + +func ExampleIntArray_PopLeft() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.PopLeft() + fmt.Println(s.Slice()) + + // Output: + // [10,20,15,30] + // [20 15 30] +} + +func ExampleIntArray_PopRight() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.PopRight() + fmt.Println(s.Slice()) + + // Output: + // [10,20,15,30] + // [10 20 15] +} + +func ExampleIntArray_PopRand() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60, 70}) + fmt.Println(s) + r, _ := s.PopRand() + fmt.Println(s) + fmt.Println(r) + + // May Output: + // [10,20,15,30,40,50,60,70] + // [10,20,15,30,40,60,70] + // 50 +} + +func ExampleIntArray_PopRands() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.PopRands(2) + fmt.Println(s) + fmt.Println(r) + + // May Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40] + // [50 60] +} + +func ExampleIntArray_PopLefts() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.PopLefts(2) + fmt.Println(s) + fmt.Println(r) + + // Output: + // [10,20,15,30,40,50,60] + // [15,30,40,50,60] + // [10 20] +} + +func ExampleIntArray_PopRights() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.PopRights(2) + fmt.Println(s) + fmt.Println(r) + + // Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40] + // [50 60] +} + +func ExampleIntArray_Range() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.Range(2, 5) + fmt.Println(r) + + // Output: + // [10,20,15,30,40,50,60] + // [15 30 40] +} + +func ExampleIntArray_SubSlice() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.SubSlice(3, 4) + fmt.Println(r) + + // Output: + // [10,20,15,30,40,50,60] + // [30 40 50 60] +} + +func ExampleIntArray_Append() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + s.Append(96, 97, 98) + fmt.Println(s) + + // Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40,50,60,96,97,98] +} + +func ExampleIntArray_Len() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Len()) + + // Output: + // [10,20,15,30,40,50,60] + // 7 +} + +func ExampleIntArray_Slice() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s.Slice()) + + // Output: + // [10 20 15 30 40 50 60] +} + +func ExampleIntArray_Interfaces() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + r := s.Interfaces() + fmt.Println(r) + + // Output: + // [10 20 15 30 40 50 60] +} + +func ExampleIntArray_Clone() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.Clone() + fmt.Println(r) + + // Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40,50,60] +} + +func ExampleIntArray_Clear() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Clear()) + fmt.Println(s) + + // Output: + // [10,20,15,30,40,50,60] + // [] + // [] +} + +func ExampleIntArray_Contains() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s.Contains(20)) + fmt.Println(s.Contains(21)) + + // Output: + // true + // false +} + +func ExampleIntArray_Search() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s.Search(20)) + fmt.Println(s.Search(21)) + + // Output: + // 1 + // -1 +} + +func ExampleIntArray_Unique() { + s := garray.NewIntArray() + s.SetArray(g.SliceInt{10, 20, 15, 15, 20, 50, 60}) + fmt.Println(s) + fmt.Println(s.Unique()) + + // Output: + // [10,20,15,15,20,50,60] + // [10,20,15,50,60] +} + +func ExampleIntArray_LockFunc() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.LockFunc(func(array []int) { + for i := 0; i < len(array)-1; i++ { + fmt.Println(array[i]) + } + }) + + // Output: + // 10 + // 20 + // 15 + // 30 + // 40 + // 50 +} + +func ExampleIntArray_RLockFunc() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.RLockFunc(func(array []int) { + for i := 0; i < len(array); i++ { + fmt.Println(array[i]) + } + }) + + // Output: + // 10 + // 20 + // 15 + // 30 + // 40 + // 50 + // 60 +} + +func ExampleIntArray_Merge() { + s1 := garray.NewIntArray() + s2 := garray.NewIntArray() + s1.SetArray(g.SliceInt{10, 20, 15}) + s2.SetArray(g.SliceInt{40, 50, 60}) + fmt.Println(s1) + fmt.Println(s2) + s1.Merge(s2) + fmt.Println(s1) + + // Output: + // [10,20,15] + // [40,50,60] + // [10,20,15,40,50,60] +} + +func ExampleIntArray_Fill() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + s.Fill(2, 3, 99) + fmt.Println(s) + + // Output: + // [10,20,15,30,40,50,60] + // [10,20,99,99,99,50,60] +} + +func ExampleIntArray_Chunk() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.Chunk(3) + fmt.Println(r) + + // Output: + // [10,20,15,30,40,50,60] + // [[10 20 15] [30 40 50] [60]] +} + +func ExampleIntArray_Pad() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.Pad(8, 99) + fmt.Println(s) + s.Pad(-10, 89) + fmt.Println(s) + + // Output: + // [10,20,15,30,40,50,60,99] + // [89,89,10,20,15,30,40,50,60,99] +} + +func ExampleIntArray_Rand() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Rand()) + + // May Output: + // [10,20,15,30,40,50,60] + // 10 true +} + +func ExampleIntArray_Rands() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Rands(3)) + + // May Output: + // [10,20,15,30,40,50,60] + // [20 50 20] +} + +func ExampleIntArray_Shuffle() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Shuffle()) + + // May Output: + // [10,20,15,30,40,50,60] + // [10,40,15,50,20,60,30] +} + +func ExampleIntArray_Reverse() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Reverse()) + + // Output: + // [10,20,15,30,40,50,60] + // [60,50,40,30,15,20,10] +} + +func ExampleIntArray_Join() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Join(",")) + + // Output: + // [10,20,15,30,40,50,60] + // 10,20,15,30,40,50,60 +} + +func ExampleIntArray_CountValues() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 15, 40, 40, 40}) + fmt.Println(s.CountValues()) + + // Output: + // map[10:1 15:2 20:1 40:3] +} + +func ExampleIntArray_Iterator() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.Iterator(func(k int, v int) bool { + fmt.Println(k, v) + return true + }) + + // Output: + // 0 10 + // 1 20 + // 2 15 + // 3 30 + // 4 40 + // 5 50 + // 6 60 +} + +func ExampleIntArray_IteratorAsc() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.IteratorAsc(func(k int, v int) bool { + fmt.Println(k, v) + return true + }) + + // Output: + // 0 10 + // 1 20 + // 2 15 + // 3 30 + // 4 40 + // 5 50 + // 6 60 +} + +func ExampleIntArray_IteratorDesc() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.IteratorDesc(func(k int, v int) bool { + fmt.Println(k, v) + return true + }) + + // Output: + // 6 60 + // 5 50 + // 4 40 + // 3 30 + // 2 15 + // 1 20 + // 0 10 +} + +func ExampleIntArray_String() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.String()) + + // Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40,50,60] +} + +func ExampleIntArray_MarshalJSON() { + type Student struct { + Id int + Name string + Scores garray.IntArray + } + var array garray.IntArray + array.SetArray(g.SliceInt{98, 97, 96}) + s := Student{ + Id: 1, + Name: "john", + Scores: array, + } + b, _ := json.Marshal(s) + fmt.Println(string(b)) + + // Output: + // {"Id":1,"Name":"john","Scores":[98,97,96]} +} + +func ExampleIntArray_UnmarshalJSON() { + b := []byte(`{"Id":1,"Name":"john","Scores":[98,96,97]}`) + type Student struct { + Id int + Name string + Scores *garray.IntArray + } + s := Student{} + json.Unmarshal(b, &s) + fmt.Println(s) + + // Output: + // {1 john [98,96,97]} +} + +func ExampleIntArray_UnmarshalValue() { + type Student struct { + Name string + Scores *garray.IntArray + } + + var s *Student + gconv.Struct(g.Map{ + "name": "john", + "scores": g.SliceInt{96, 98, 97}, + }, &s) + fmt.Println(s) + + // Output: + // &{john [96,98,97]} +} + +func ExampleIntArray_FilterEmpty() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 40, 50, 0, 0, 0, 60}) + fmt.Println(s) + fmt.Println(s.FilterEmpty()) + + // Output: + // [10,40,50,0,0,0,60] + // [10,40,50,60] +} + +func ExampleIntArray_IsEmpty() { + s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s.IsEmpty()) + s1 := garray.NewIntArray() + fmt.Println(s1.IsEmpty()) + + // Output: + // false + // true +} diff --git a/container/garray/garray_z_example_sorted_str_test.go b/container/garray/garray_z_example_sorted_str_test.go new file mode 100644 index 000000000..0c9c83a51 --- /dev/null +++ b/container/garray/garray_z_example_sorted_str_test.go @@ -0,0 +1,573 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package garray_test + +import ( + "fmt" + "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/util/gconv" +) + +func ExampleSortedStrArray_Walk() { + var array garray.SortedStrArray + tables := g.SliceStr{"user", "user_detail"} + prefix := "gf_" + array.Append(tables...) + // Add prefix for given table names. + array.Walk(func(value string) string { + return prefix + value + }) + fmt.Println(array.Slice()) + + // Output: + // [gf_user gf_user_detail] +} + +func ExampleNewSortedStrArray() { + s := garray.NewSortedStrArray() + s.Append("b") + s.Append("d") + s.Append("c") + s.Append("a") + fmt.Println(s.Slice()) + + // Output: + // [a b c d] +} + +func ExampleNewSortedStrArraySize() { + s := garray.NewSortedStrArraySize(3) + s.SetArray([]string{"b", "d", "a", "c"}) + fmt.Println(s.Slice(), s.Len(), cap(s.Slice())) + + // Output: + // [a b c d] 4 4 +} + +func ExampleNewStrArrayFromCopy() { + s := garray.NewSortedStrArrayFromCopy(g.SliceStr{"b", "d", "c", "a"}) + fmt.Println(s.Slice()) + + // Output: + // [a b c d] +} + +func ExampleSortedStrArray_At() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "d", "c", "a"}) + sAt := s.At(2) + fmt.Println(s) + fmt.Println(sAt) + + // Output: + // ["a","b","c","d"] + // c + +} + +func ExampleSortedStrArray_Get() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "d", "c", "a", "e"}) + sGet, sBool := s.Get(3) + fmt.Println(s) + fmt.Println(sGet, sBool) + + // Output: + // ["a","b","c","d","e"] + // d true +} + +func ExampleSortedStrArray_SetArray() { + s := garray.NewSortedStrArray() + s.SetArray([]string{"b", "d", "a", "c"}) + fmt.Println(s.Slice()) + + // Output: + // [a b c d] +} + +func ExampleSortedStrArray_SetUnique() { + s := garray.NewSortedStrArray() + s.SetArray([]string{"b", "d", "a", "c", "c", "a"}) + fmt.Println(s.SetUnique(true)) + + // Output: + // ["a","b","c","d"] +} + +func ExampleSortedStrArray_Sum() { + s := garray.NewSortedStrArray() + s.SetArray([]string{"5", "3", "2"}) + fmt.Println(s) + a := s.Sum() + fmt.Println(a) + + // Output: + // ["2","3","5"] + // 10 +} + +func ExampleSortedStrArray_Sort() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"b", "d", "a", "c"}) + fmt.Println(s) + a := s.Sort() + fmt.Println(a) + + // Output: + // ["a","b","c","d"] + // ["a","b","c","d"] +} + +func ExampleSortedStrArray_Remove() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"b", "d", "c", "a"}) + fmt.Println(s.Slice()) + s.Remove(1) + fmt.Println(s.Slice()) + + // Output: + // [a b c d] + // [a c d] +} + +func ExampleSortedStrArray_RemoveValue() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"b", "d", "c", "a"}) + fmt.Println(s.Slice()) + s.RemoveValue("b") + fmt.Println(s.Slice()) + + // Output: + // [a b c d] + // [a c d] +} + +func ExampleSortedStrArray_PopLeft() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"b", "d", "c", "a"}) + r, _ := s.PopLeft() + fmt.Println(r) + fmt.Println(s.Slice()) + + // Output: + // a + // [b c d] +} + +func ExampleSortedStrArray_PopRight() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"b", "d", "c", "a"}) + fmt.Println(s.Slice()) + r, _ := s.PopRight() + fmt.Println(r) + fmt.Println(s.Slice()) + + // Output: + // [a b c d] + // d + // [a b c] +} + +func ExampleSortedStrArray_PopRights() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + r := s.PopRights(2) + fmt.Println(r) + fmt.Println(s) + + // Output: + // [g h] + // ["a","b","c","d","e","f"] +} + +func ExampleSortedStrArray_Rand() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + r, _ := s.PopRand() + fmt.Println(r) + fmt.Println(s) + + // May Output: + // b + // ["a","c","d","e","f","g","h"] +} + +func ExampleSortedStrArray_PopRands() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + r := s.PopRands(2) + fmt.Println(r) + fmt.Println(s) + + // May Output: + // [d a] + // ["b","c","e","f","g","h"] +} + +func ExampleSortedStrArray_PopLefts() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + r := s.PopLefts(2) + fmt.Println(r) + fmt.Println(s) + + // Output: + // [a b] + // ["c","d","e","f","g","h"] +} + +func ExampleSortedStrArray_Range() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + r := s.Range(2, 5) + fmt.Println(r) + + // Output: + // [c d e] +} + +func ExampleSortedStrArray_SubSlice() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + r := s.SubSlice(3, 4) + fmt.Println(s.Slice()) + fmt.Println(r) + + // Output: + // [a b c d e f g h] + // [d e f g] +} + +func ExampleSortedStrArray_Add() { + s := garray.NewSortedStrArray() + s.Add("b", "d", "c", "a") + fmt.Println(s) + + // Output: + // ["a","b","c","d"] +} + +func ExampleSortedStrArray_Append() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"b", "d", "c", "a"}) + fmt.Println(s) + s.Append("f", "e", "g") + fmt.Println(s) + + // Output: + // ["a","b","c","d"] + // ["a","b","c","d","e","f","g"] +} + +func ExampleSortedStrArray_Len() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + fmt.Println(s) + fmt.Println(s.Len()) + + // Output: + // ["a","b","c","d","e","f","g","h"] + // 8 +} + +func ExampleSortedStrArray_Slice() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + fmt.Println(s.Slice()) + + // Output: + // [a b c d e f g h] +} + +func ExampleSortedStrArray_Interfaces() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + r := s.Interfaces() + fmt.Println(r) + + // Output: + // [a b c d e f g h] +} + +func ExampleSortedStrArray_Clone() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + r := s.Clone() + fmt.Println(r) + fmt.Println(s) + + // Output: + // ["a","b","c","d","e","f","g","h"] + // ["a","b","c","d","e","f","g","h"] +} + +func ExampleSortedStrArray_Clear() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + fmt.Println(s) + fmt.Println(s.Clear()) + fmt.Println(s) + + // Output: + // ["a","b","c","d","e","f","g","h"] + // [] + // [] +} + +func ExampleSortedStrArray_Contains() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + fmt.Println(s.Contains("e")) + fmt.Println(s.Contains("E")) + fmt.Println(s.Contains("z")) + + // Output: + // true + // false + // false +} + +func ExampleSortedStrArray_ContainsI() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + fmt.Println(s) + fmt.Println(s.ContainsI("E")) + fmt.Println(s.ContainsI("z")) + + // Output: + // ["a","b","c","d","e","f","g","h"] + // true + // false +} + +func ExampleSortedStrArray_Search() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + fmt.Println(s) + fmt.Println(s.Search("e")) + fmt.Println(s.Search("E")) + fmt.Println(s.Search("z")) + + // Output: + // ["a","b","c","d","e","f","g","h"] + // 4 + // -1 + // -1 +} + +func ExampleSortedStrArray_Unique() { + s := garray.NewSortedStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "c", "c", "d", "d"}) + fmt.Println(s) + fmt.Println(s.Unique()) + + // Output: + // ["a","b","c","c","c","d","d"] + // ["a","b","c","d"] +} + +func ExampleSortedStrArray_LockFunc() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "c", "a"}) + s.LockFunc(func(array []string) { + array[len(array)-1] = "GF fans" + }) + fmt.Println(s) + + // Output: + // ["a","b","GF fans"] +} + +func ExampleSortedStrArray_RLockFunc() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "c", "a"}) + s.RLockFunc(func(array []string) { + array[len(array)-1] = "GF fans" + fmt.Println(array[len(array)-1]) + }) + fmt.Println(s) + + // Output: + // GF fans + // ["a","b","GF fans"] +} + +func ExampleSortedStrArray_Merge() { + s1 := garray.NewSortedStrArray() + s2 := garray.NewSortedStrArray() + s1.SetArray(g.SliceStr{"b", "c", "a"}) + s2.SetArray(g.SliceStr{"e", "d", "f"}) + fmt.Println(s1) + fmt.Println(s2) + s1.Merge(s2) + fmt.Println(s1) + + // Output: + // ["a","b","c"] + // ["d","e","f"] + // ["a","b","c","d","e","f"] +} + +func ExampleSortedStrArray_Chunk() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + r := s.Chunk(3) + fmt.Println(r) + + // Output: + // [[a b c] [d e f] [g h]] +} + +func ExampleSortedStrArray_Rands() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + fmt.Println(s) + fmt.Println(s.Rands(3)) + + // May Output: + // ["a","b","c","d","e","f","g","h"] + // [h g c] +} + +func ExampleSortedStrArray_Join() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"c", "b", "a", "d", "f", "e", "h", "g"}) + fmt.Println(s.Join(",")) + + // Output: + // a,b,c,d,e,f,g,h +} + +func ExampleSortedStrArray_CountValues() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"a", "b", "c", "c", "c", "d", "d"}) + fmt.Println(s.CountValues()) + + // Output: + // map[a:1 b:1 c:3 d:2] +} + +func ExampleSortedStrArray_Iterator() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "c", "a"}) + s.Iterator(func(k int, v string) bool { + fmt.Println(k, v) + return true + }) + + // Output: + // 0 a + // 1 b + // 2 c +} + +func ExampleSortedStrArray_IteratorAsc() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "c", "a"}) + s.IteratorAsc(func(k int, v string) bool { + fmt.Println(k, v) + return true + }) + + // Output: + // 0 a + // 1 b + // 2 c +} + +func ExampleSortedStrArray_IteratorDesc() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "c", "a"}) + s.IteratorDesc(func(k int, v string) bool { + fmt.Println(k, v) + return true + }) + + // Output: + // 2 c + // 1 b + // 0 a +} + +func ExampleSortedStrArray_String() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "c", "a"}) + fmt.Println(s.String()) + + // Output: + // ["a","b","c"] +} + +func ExampleSortedStrArray_MarshalJSON() { + type Student struct { + ID int + Name string + Levels garray.SortedStrArray + } + r := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "c", "a"}) + s := Student{ + ID: 1, + Name: "john", + Levels: *r, + } + b, _ := json.Marshal(s) + fmt.Println(string(b)) + + // Output: + // {"ID":1,"Name":"john","Levels":["a","b","c"]} +} + +func ExampleSortedStrArray_UnmarshalJSON() { + b := []byte(`{"Id":1,"Name":"john","Lessons":["Math","English","Sport"]}`) + type Student struct { + Id int + Name string + Lessons *garray.StrArray + } + s := Student{} + json.Unmarshal(b, &s) + fmt.Println(s) + + // Output: + // {1 john ["Math","English","Sport"]} +} + +func ExampleSortedStrArray_UnmarshalValue() { + type Student struct { + Name string + Lessons *garray.StrArray + } + var s *Student + gconv.Struct(g.Map{ + "name": "john", + "lessons": []byte(`["Math","English","Sport"]`), + }, &s) + fmt.Println(s) + + var s1 *Student + gconv.Struct(g.Map{ + "name": "john", + "lessons": g.SliceStr{"Math", "English", "Sport"}, + }, &s1) + fmt.Println(s1) + + // Output: + // &{john ["Math","English","Sport"]} + // &{john ["Math","English","Sport"]} +} + +func ExampleSortedStrArray_FilterEmpty() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "a", "", "c", "", "", "d"}) + fmt.Println(s) + fmt.Println(s.FilterEmpty()) + + // Output: + // ["","","","a","b","c","d"] + // ["a","b","c","d"] +} + +func ExampleSortedStrArray_IsEmpty() { + s := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "a", "", "c", "", "", "d"}) + fmt.Println(s.IsEmpty()) + s1 := garray.NewSortedStrArray() + fmt.Println(s1.IsEmpty()) + + // Output: + // false + // true +} diff --git a/container/garray/garray_z_example_str_test.go b/container/garray/garray_z_example_str_test.go index 8091e8955..f07bded82 100644 --- a/container/garray/garray_z_example_str_test.go +++ b/container/garray/garray_z_example_str_test.go @@ -10,6 +10,9 @@ import ( "fmt" "github.com/gogf/gf/v2/container/garray" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" ) func ExampleStrArray_Walk() { @@ -26,3 +29,621 @@ func ExampleStrArray_Walk() { // Output: // [gf_user gf_user_detail] } + +func ExampleStrArray_NewStrArray() { + s := garray.NewStrArray() + s.Append("We") + s.Append("are") + s.Append("GF") + s.Append("fans") + fmt.Println(s.Slice()) + + // Output: + // [We are GF fans] +} + +func ExampleStrArray_NewStrArraySize() { + s := garray.NewStrArraySize(3, 5) + s.Set(0, "We") + s.Set(1, "are") + s.Set(2, "GF") + s.Set(3, "fans") + fmt.Println(s.Slice(), s.Len(), cap(s.Slice())) + + // Output: + // [We are GF] 3 5 +} + +func ExampleStrArray_NewStrArrayFrom() { + s := garray.NewStrArrayFrom(g.SliceStr{"We", "are", "GF", "fans", "!"}) + fmt.Println(s.Slice(), s.Len(), cap(s.Slice())) + + // Output: + // [We are GF fans !] 5 5 +} + +func ExampleStrArray_NewStrArrayFromCopy() { + s := garray.NewStrArrayFromCopy(g.SliceStr{"We", "are", "GF", "fans", "!"}) + fmt.Println(s.Slice(), s.Len(), cap(s.Slice())) + + // Output: + // [We are GF fans !] 5 5 +} + +func ExampleStrArray_At() { + s := garray.NewStrArrayFrom(g.SliceStr{"We", "are", "GF", "fans", "!"}) + sAt := s.At(2) + fmt.Println(sAt) + + // Output: + // GF +} + +func ExampleStrArray_Get() { + s := garray.NewStrArrayFrom(g.SliceStr{"We", "are", "GF", "fans", "!"}) + sGet, sBool := s.Get(3) + fmt.Println(sGet, sBool) + + // Output: + // fans true +} + +func ExampleStrArray_Set() { + s := garray.NewStrArraySize(3, 5) + s.Set(0, "We") + s.Set(1, "are") + s.Set(2, "GF") + s.Set(3, "fans") + fmt.Println(s.Slice()) + + // Output: + // [We are GF] +} + +func ExampleStrArray_SetArray() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"We", "are", "GF", "fans", "!"}) + fmt.Println(s.Slice()) + + // Output: + // [We are GF fans !] +} + +func ExampleStrArray_Replace() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"We", "are", "GF", "fans", "!"}) + fmt.Println(s.Slice()) + s.Replace(g.SliceStr{"Happy", "coding"}) + fmt.Println(s.Slice()) + + // Output: + // [We are GF fans !] + // [Happy coding GF fans !] +} + +func ExampleStrArray_Sum() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"3", "5", "10"}) + a := s.Sum() + fmt.Println(a) + + // Output: + // 18 +} + +func ExampleStrArray_Sort() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"b", "d", "a", "c"}) + a := s.Sort() + fmt.Println(a) + + // Output: + // ["a","b","c","d"] +} + +func ExampleStrArray_SortFunc() { + s := garray.NewStrArrayFrom(g.SliceStr{"b", "c", "a"}) + fmt.Println(s) + s.SortFunc(func(v1, v2 string) bool { + return gstr.Compare(v1, v2) > 0 + }) + fmt.Println(s) + s.SortFunc(func(v1, v2 string) bool { + return gstr.Compare(v1, v2) < 0 + }) + fmt.Println(s) + + // Output: + // ["b","c","a"] + // ["c","b","a"] + // ["a","b","c"] +} + +func ExampleStrArray_InsertBefore() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.InsertBefore(1, "here") + fmt.Println(s.Slice()) + + // Output: + // [a here b c d] +} + +func ExampleStrArray_InsertAfter() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.InsertAfter(1, "here") + fmt.Println(s.Slice()) + + // Output: + // [a b here c d] +} + +func ExampleStrArray_Remove() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.Remove(1) + fmt.Println(s.Slice()) + + // Output: + // [a c d] +} + +func ExampleStrArray_RemoveValue() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.RemoveValue("b") + fmt.Println(s.Slice()) + + // Output: + // [a c d] +} + +func ExampleStrArray_PushLeft() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.PushLeft("We", "are", "GF", "fans") + fmt.Println(s.Slice()) + + // Output: + // [We are GF fans a b c d] +} + +func ExampleStrArray_PushRight() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.PushRight("We", "are", "GF", "fans") + fmt.Println(s.Slice()) + + // Output: + // [a b c d We are GF fans] +} + +func ExampleStrArray_PopLeft() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.PopLeft() + fmt.Println(s.Slice()) + + // Output: + // [b c d] +} + +func ExampleStrArray_PopRight() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.PopRight() + fmt.Println(s.Slice()) + + // Output: + // [a b c] +} + +func ExampleStrArray_PopRand() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r, _ := s.PopRand() + fmt.Println(r) + + // May Output: + // e +} + +func ExampleStrArray_PopRands() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.PopRands(2) + fmt.Println(r) + + // May Output: + // [e c] +} + +func ExampleStrArray_PopLefts() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.PopLefts(2) + fmt.Println(r) + fmt.Println(s) + + // Output: + // [a b] + // ["c","d","e","f","g","h"] +} + +func ExampleStrArray_PopRights() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.PopRights(2) + fmt.Println(r) + fmt.Println(s) + + // Output: + // [g h] + // ["a","b","c","d","e","f"] +} + +func ExampleStrArray_Range() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.Range(2, 5) + fmt.Println(r) + + // Output: + // [c d e] +} + +func ExampleStrArray_SubSlice() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.SubSlice(3, 4) + fmt.Println(r) + + // Output: + // [d e f g] +} + +func ExampleStrArray_Append() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"We", "are", "GF", "fans"}) + s.Append("a", "b", "c") + fmt.Println(s) + + // Output: + // ["We","are","GF","fans","a","b","c"] +} + +func ExampleStrArray_Len() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Len()) + + // Output: + // 8 +} + +func ExampleStrArray_Slice() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Slice()) + + // Output: + // [a b c d e f g h] +} + +func ExampleStrArray_Interfaces() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.Interfaces() + fmt.Println(r) + + // Output: + // [a b c d e f g h] +} + +func ExampleStrArray_Clone() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.Clone() + fmt.Println(r) + fmt.Println(s) + + // Output: + // ["a","b","c","d","e","f","g","h"] + // ["a","b","c","d","e","f","g","h"] +} + +func ExampleStrArray_Clear() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s) + fmt.Println(s.Clear()) + fmt.Println(s) + + // Output: + // ["a","b","c","d","e","f","g","h"] + // [] + // [] +} + +func ExampleStrArray_Contains() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Contains("e")) + fmt.Println(s.Contains("z")) + + // Output: + // true + // false +} + +func ExampleStrArray_ContainsI() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.ContainsI("E")) + fmt.Println(s.ContainsI("z")) + + // Output: + // true + // false +} + +func ExampleStrArray_Search() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Search("e")) + fmt.Println(s.Search("z")) + + // Output: + // 4 + // -1 +} + +func ExampleStrArray_Unique() { + s := garray.NewStrArray() + s.SetArray(g.SliceStr{"a", "b", "c", "c", "c", "d", "d"}) + fmt.Println(s.Unique()) + + // Output: + // ["a","b","c","d"] +} + +func ExampleStrArray_LockFunc() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c"}) + s.LockFunc(func(array []string) { + array[len(array)-1] = "GF fans" + }) + fmt.Println(s) + + // Output: + // ["a","b","GF fans"] +} + +func ExampleStrArray_RLockFunc() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c", "d", "e"}) + s.RLockFunc(func(array []string) { + for i := 0; i < len(array); i++ { + fmt.Println(array[i]) + } + }) + + // Output: + // a + // b + // c + // d + // e +} + +func ExampleStrArray_Merge() { + s1 := garray.NewStrArray() + s2 := garray.NewStrArray() + s1.SetArray(g.SliceStr{"a", "b", "c"}) + s2.SetArray(g.SliceStr{"d", "e", "f"}) + s1.Merge(s2) + fmt.Println(s1) + + // Output: + // ["a","b","c","d","e","f"] +} + +func ExampleStrArray_Fill() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + s.Fill(2, 3, "here") + fmt.Println(s) + + // Output: + // ["a","b","here","here","here","f","g","h"] +} + +func ExampleStrArray_Chunk() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.Chunk(3) + fmt.Println(r) + + // Output: + // [[a b c] [d e f] [g h]] +} + +func ExampleStrArray_Pad() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c"}) + s.Pad(7, "here") + fmt.Println(s) + s.Pad(-10, "there") + fmt.Println(s) + + // Output: + // ["a","b","c","here","here","here","here"] + // ["there","there","there","a","b","c","here","here","here","here"] +} + +func ExampleStrArray_Rand() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Rand()) + + // May Output: + // c true +} + +func ExampleStrArray_Rands() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Rands(3)) + + // May Output: + // [e h e] +} + +func ExampleStrArray_Shuffle() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Shuffle()) + + // May Output: + // ["a","c","e","d","b","g","f","h"] +} + +func ExampleStrArray_Reverse() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Reverse()) + + // Output: + // ["h","g","f","e","d","c","b","a"] +} + +func ExampleStrArray_Join() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c"}) + fmt.Println(s.Join(",")) + + // Output: + // a,b,c +} + +func ExampleStrArray_CountValues() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c", "c", "c", "d", "d"}) + fmt.Println(s.CountValues()) + + // Output: + // map[a:1 b:1 c:3 d:2] +} + +func ExampleStrArray_Iterator() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c"}) + s.Iterator(func(k int, v string) bool { + fmt.Println(k, v) + return true + }) + + // Output: + // 0 a + // 1 b + // 2 c +} + +func ExampleStrArray_IteratorAsc() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c"}) + s.IteratorAsc(func(k int, v string) bool { + fmt.Println(k, v) + return true + }) + + // Output: + // 0 a + // 1 b + // 2 c +} + +func ExampleStrArray_IteratorDesc() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c"}) + s.IteratorDesc(func(k int, v string) bool { + fmt.Println(k, v) + return true + }) + + // Output: + // 2 c + // 1 b + // 0 a +} + +func ExampleStrArray_String() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c"}) + fmt.Println(s.String()) + + // Output: + // ["a","b","c"] +} + +func ExampleStrArray_MarshalJSON() { + type Student struct { + Id int + Name string + Lessons []string + } + s := Student{ + Id: 1, + Name: "john", + Lessons: []string{"Math", "English", "Music"}, + } + b, _ := json.Marshal(s) + fmt.Println(string(b)) + + // Output: + // {"Id":1,"Name":"john","Lessons":["Math","English","Music"]} +} + +func ExampleStrArray_UnmarshalJSON() { + b := []byte(`{"Id":1,"Name":"john","Lessons":["Math","English","Sport"]}`) + type Student struct { + Id int + Name string + Lessons *garray.StrArray + } + s := Student{} + json.Unmarshal(b, &s) + fmt.Println(s) + + // Output: + // {1 john ["Math","English","Sport"]} +} + +func ExampleStrArray_UnmarshalValue() { + type Student struct { + Name string + Lessons *garray.StrArray + } + var s *Student + gconv.Struct(g.Map{ + "name": "john", + "lessons": []byte(`["Math","English","Sport"]`), + }, &s) + fmt.Println(s) + + var s1 *Student + gconv.Struct(g.Map{ + "name": "john", + "lessons": g.SliceStr{"Math", "English", "Sport"}, + }, &s1) + fmt.Println(s1) + + // Output: + // &{john ["Math","English","Sport"]} + // &{john ["Math","English","Sport"]} +} + +func ExampleStrArray_FilterEmpty() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "", "c", "", "", "d"}) + fmt.Println(s.FilterEmpty()) + + // Output: + // ["a","b","c","d"] +} + +func ExampleStrArray_IsEmpty() { + s := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "", "c", "", "", "d"}) + fmt.Println(s.IsEmpty()) + s1 := garray.NewStrArray() + fmt.Println(s1.IsEmpty()) + + // Output: + // false + // true +} diff --git a/container/gset/gset_z_example_int_test.go b/container/gset/gset_z_example_int_test.go index 761e3552f..d5d2cb411 100644 --- a/container/gset/gset_z_example_int_test.go +++ b/container/gset/gset_z_example_int_test.go @@ -7,17 +7,401 @@ package gset_test import ( + "encoding/json" "fmt" "github.com/gogf/gf/v2/container/gset" + "github.com/gogf/gf/v2/frame/g" ) +// New create and returns a new set, which contains un-repeated items. +// The parameter `safe` is used to specify whether using set in concurrent-safety, +// which is false in default. +func ExampleNewIntSet() { + intSet := gset.NewIntSet() + intSet.Add([]int{1, 2, 3}...) + fmt.Println(intSet.Slice()) + + // May Output: + // [2 1 3] +} + +// NewIntSetFrom returns a new set from `items`. +func ExampleNewFrom() { + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) + fmt.Println(intSet.Slice()) + + // May Output: + // [2 1 3] +} + +// Add adds one or multiple items to the set. +func ExampleIntSet_Add() { + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) + intSet.Add(1) + fmt.Println(intSet.Slice()) + fmt.Println(intSet.AddIfNotExist(1)) + + // Mya Output: + // [1 2 3] + // false +} + +// AddIfNotExist checks whether item exists in the set, +// it adds the item to set and returns true if it does not exists in the set, +// or else it does nothing and returns false. +func ExampleIntSet_AddIfNotExist() { + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) + intSet.Add(1) + fmt.Println(intSet.Slice()) + fmt.Println(intSet.AddIfNotExist(1)) + + // Mya Output: + // [1 2 3] + // false +} + +// AddIfNotExistFunc checks whether item exists in the set, +// it adds the item to set and returns true if it does not exists in the set and function `f` returns true, +// or else it does nothing and returns false. +// Note that, the function `f` is executed without writing lock. +func ExampleIntSet_AddIfNotExistFunc() { + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) + intSet.Add(1) + fmt.Println(intSet.Slice()) + fmt.Println(intSet.AddIfNotExistFunc(5, func() bool { + return true + })) + + // May Output: + // [1 2 3] + // true +} + +// AddIfNotExistFunc checks whether item exists in the set, +// it adds the item to set and returns true if it does not exists in the set and function `f` returns true, +// or else it does nothing and returns false. +// Note that, the function `f` is executed without writing lock. +func ExampleIntSet_AddIfNotExistFuncLock() { + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) + intSet.Add(1) + fmt.Println(intSet.Slice()) + fmt.Println(intSet.AddIfNotExistFuncLock(4, func() bool { + return true + })) + + // May Output: + // [1 2 3] + // true +} + +// Clear deletes all items of the set. +func ExampleIntSet_Clear() { + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) + fmt.Println(intSet.Size()) + intSet.Clear() + fmt.Println(intSet.Size()) + + // Output: + // 3 + // 0 +} + +// Complement returns a new set which is the complement from `set` to `full`. +// Which means, all the items in `newSet` are in `full` and not in `set`. +// It returns the difference between `full` and `set` if the given set `full` is not the full set of `set`. +func ExampleIntSet_Complement() { + intSet := gset.NewIntSetFrom([]int{1, 2, 3, 4, 5}) + s := gset.NewIntSetFrom([]int{1, 2, 3}) + fmt.Println(s.Complement(intSet).Slice()) + + // May Output: + // [4 5] +} + +// Contains checks whether the set contains `item`. func ExampleIntSet_Contains() { - var set gset.IntSet - set.Add(1) - fmt.Println(set.Contains(1)) - fmt.Println(set.Contains(2)) + var set1 gset.IntSet + set1.Add(1, 4, 5, 6, 7) + fmt.Println(set1.Contains(1)) + + var set2 gset.IntSet + set2.Add(1, 4, 5, 6, 7) + fmt.Println(set2.Contains(8)) // Output: // true // false } + +// Diff returns a new set which is the difference set from `set` to `other`. +// Which means, all the items in `newSet` are in `set` but not in `other`. +func ExampleIntSet_Diff() { + s1 := gset.NewIntSetFrom([]int{1, 2, 3}) + s2 := gset.NewIntSetFrom([]int{1, 2, 3, 4}) + fmt.Println(s2.Diff(s1).Slice()) + + // Output: + // [4] +} + +// Equal checks whether the two sets equal. +func ExampleIntSet_Equal() { + s1 := gset.NewIntSetFrom([]int{1, 2, 3}) + s2 := gset.NewIntSetFrom([]int{1, 2, 3, 4}) + fmt.Println(s2.Equal(s1)) + + s3 := gset.NewIntSetFrom([]int{1, 2, 3}) + s4 := gset.NewIntSetFrom([]int{1, 2, 3}) + fmt.Println(s3.Equal(s4)) + + // Output: + // false + // true +} + +// Intersect returns a new set which is the intersection from `set` to `other`. +// Which means, all the items in `newSet` are in `set` and also in `other`. +func ExampleIntSet_Intersect() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3}...) + var s2 gset.IntSet + s2.Add([]int{1, 2, 3, 4}...) + fmt.Println(s2.Intersect(s1).Slice()) + + // May Output: + // [1 2 3] +} + +// IsSubsetOf checks whether the current set is a sub-set of `other` +func ExampleIntSet_IsSubsetOf() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + var s2 gset.IntSet + s2.Add([]int{1, 2, 4}...) + fmt.Println(s2.IsSubsetOf(s1)) + + // Output: + // true +} + +// Iterator iterates the set readonly with given callback function `f`, +// if `f` returns true then continue iterating; or false to stop. +func ExampleIntSet_Iterator() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + s1.Iterator(func(v int) bool { + fmt.Println("Iterator", v) + return true + }) + // May Output: + // Iterator 2 + // Iterator 3 + // Iterator 1 + // Iterator 4 +} + +// Join joins items with a string `glue`. +func ExampleIntSet_Join() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + fmt.Println(s1.Join(",")) + + // May Output: + // 3,4,1,2 +} + +// LockFunc locks writing with callback function `f`. +func ExampleIntSet_LockFunc() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2}...) + s1.LockFunc(func(m map[int]struct{}) { + m[3] = struct{}{} + }) + fmt.Println(s1.Slice()) + + // May Output + // [2 3 1] +} + +// MarshalJSON implements the interface MarshalJSON for json.Marshal. +func ExampleIntSet_MarshalJSON() { + type Student struct { + Id int + Name string + Scores *gset.IntSet + } + s := Student{ + Id: 1, + Name: "john", + Scores: gset.NewIntSetFrom([]int{100, 99, 98}), + } + b, _ := json.Marshal(s) + fmt.Println(string(b)) + + // May Output: + // {"Id":1,"Name":"john","Scores":[100,99,98]} +} + +// Merge adds items from `others` sets into `set`. +func ExampleIntSet_Merge() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + + s2 := gset.NewIntSet() + fmt.Println(s1.Merge(s2).Slice()) + + // May Output: + // [1 2 3 4] +} + +// Pops randomly pops an item from set. +func ExampleIntSet_Pop() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + + fmt.Println(s1.Pop()) + + // May Output: + // 1 +} + +// Pops randomly pops `size` items from set. +// It returns all items if size == -1. +func ExampleIntSet_Pops() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + for _, v := range s1.Pops(2) { + fmt.Println(v) + } + + // May Output: + // 1 + // 2 +} + +// RLockFunc locks reading with callback function `f`. +func ExampleIntSet_RLockFunc() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + s1.RLockFunc(func(m map[int]struct{}) { + fmt.Println(m) + }) + + // Output: + // map[1:{} 2:{} 3:{} 4:{}] +} + +// Remove deletes `item` from set. +func ExampleIntSet_Remove() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + s1.Remove(1) + fmt.Println(s1.Slice()) + + // May Output: + // [3 4 2] +} + +// Size returns the size of the set. +func ExampleIntSet_Size() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + fmt.Println(s1.Size()) + + // Output: + // 4 +} + +// Slice returns the a of items of the set as slice. +func ExampleIntSet_Slice() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + fmt.Println(s1.Slice()) + + // May Output: + // [1, 2, 3, 4] +} + +// String returns items as a string, which implements like json.Marshal does. +func ExampleIntSet_String() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + fmt.Println(s1.String()) + + // May Output: + // [1,2,3,4] +} + +// Sum sums items. Note: The items should be converted to int type, +// or you'd get a result that you unexpected. +func ExampleIntSet_Sum() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + fmt.Println(s1.Sum()) + + // Output: + // 10 +} + +// Union returns a new set which is the union of `set` and `other`. +// Which means, all the items in `newSet` are in `set` or in `other`. +func ExampleIntSet_Union() { + s1 := gset.NewIntSet() + s1.Add([]int{1, 2, 3, 4}...) + s2 := gset.NewIntSet() + s2.Add([]int{1, 2, 4}...) + fmt.Println(s1.Union(s2).Slice()) + + // May Output: + // [3 4 1 2] +} + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func ExampleIntSet_UnmarshalJSON() { + b := []byte(`{"Id":1,"Name":"john","Scores":[100,99,98]}`) + type Student struct { + Id int + Name string + Scores *gset.IntSet + } + s := Student{} + json.Unmarshal(b, &s) + fmt.Println(s) + + // May Output: + // {1 john [100,99,98]} +} + +// UnmarshalValue is an interface implement which sets any type of value for set. +func ExampleIntSet_UnmarshalValue() { + b := []byte(`{"Id":1,"Name":"john","Scores":100,99,98}`) + type Student struct { + Id int + Name string + Scores *gset.IntSet + } + s := Student{} + json.Unmarshal(b, &s) + fmt.Println(s) + + // May Output: + // {1 john [100,99,98]} +} + +// Walk applies a user supplied function `f` to every item of set. +func ExampleIntSet_Walk() { + var ( + set gset.IntSet + names = g.SliceInt{1, 0} + delta = 10 + ) + set.Add(names...) + // Add prefix for given table names. + set.Walk(func(item int) int { + return delta + item + }) + fmt.Println(set.Slice()) + + // May Output: + // [12 60] +} diff --git a/container/gset/gset_z_example_str_test.go b/container/gset/gset_z_example_str_test.go index cfa0d22e1..586e55615 100644 --- a/container/gset/gset_z_example_str_test.go +++ b/container/gset/gset_z_example_str_test.go @@ -7,24 +7,400 @@ package gset_test import ( + "encoding/json" "fmt" "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/frame/g" ) +// NewStrSet create and returns a new set, which contains un-repeated items. +// The parameter `safe` is used to specify whether using set in concurrent-safety, +// which is false in default. +func ExampleNewStrSet() { + strSet := gset.NewStrSet(true) + strSet.Add([]string{"str1", "str2", "str3"}...) + fmt.Println(strSet.Slice()) + + // May Output: + // [str3 str1 str2] +} + +// NewStrSetFrom returns a new set from `items`. +func ExampleNewStrSetFrom() { + strSet := gset.NewStrSetFrom([]string{"str1", "str2", "str3"}, true) + fmt.Println(strSet.Slice()) + + // May Output: + // [str1 str2 str3] +} + +// Add adds one or multiple items to the set. +func ExampleStrSet_Add() { + strSet := gset.NewStrSetFrom([]string{"str1", "str2", "str3"}, true) + strSet.Add("str") + fmt.Println(strSet.Slice()) + fmt.Println(strSet.AddIfNotExist("str")) + + // Mya Output: + // [str str1 str2 str3] + // false +} + +// AddIfNotExist checks whether item exists in the set, +// it adds the item to set and returns true if it does not exists in the set, +// or else it does nothing and returns false. +func ExampleStrSet_AddIfNotExist() { + strSet := gset.NewStrSetFrom([]string{"str1", "str2", "str3"}, true) + strSet.Add("str") + fmt.Println(strSet.Slice()) + fmt.Println(strSet.AddIfNotExist("str")) + + // Mya Output: + // [str str1 str2 str3] + // false +} + +// AddIfNotExistFunc checks whether item exists in the set, +// it adds the item to set and returns true if it does not exists in the set and function `f` returns true, +// or else it does nothing and returns false. +// Note that, the function `f` is executed without writing lock. +func ExampleStrSet_AddIfNotExistFunc() { + strSet := gset.NewStrSetFrom([]string{"str1", "str2", "str3"}, true) + strSet.Add("str") + fmt.Println(strSet.Slice()) + fmt.Println(strSet.AddIfNotExistFunc("str5", func() bool { + return true + })) + + // May Output: + // [str1 str2 str3 str] + // true +} + +// AddIfNotExistFunc checks whether item exists in the set, +// it adds the item to set and returns true if it does not exists in the set and function `f` returns true, +// or else it does nothing and returns false. +// Note that, the function `f` is executed without writing lock. +func ExampleStrSet_AddIfNotExistFuncLock() { + strSet := gset.NewStrSetFrom([]string{"str1", "str2", "str3"}, true) + strSet.Add("str") + fmt.Println(strSet.Slice()) + fmt.Println(strSet.AddIfNotExistFuncLock("str4", func() bool { + return true + })) + + // May Output: + // [str1 str2 str3 str] + // true +} + +// Clear deletes all items of the set. +func ExampleStrSet_Clear() { + strSet := gset.NewStrSetFrom([]string{"str1", "str2", "str3"}, true) + fmt.Println(strSet.Size()) + strSet.Clear() + fmt.Println(strSet.Size()) + + // Output: + // 3 + // 0 +} + +// Complement returns a new set which is the complement from `set` to `full`. +// Which means, all the items in `newSet` are in `full` and not in `set`. +// It returns the difference between `full` and `set` if the given set `full` is not the full set of `set`. +func ExampleStrSet_Complement() { + strSet := gset.NewStrSetFrom([]string{"str1", "str2", "str3", "str4", "str5"}, true) + s := gset.NewStrSetFrom([]string{"str1", "str2", "str3"}, true) + fmt.Println(s.Complement(strSet).Slice()) + + // May Output: + // [str4 str5] +} + +// Contains checks whether the set contains `item`. func ExampleStrSet_Contains() { var set gset.StrSet set.Add("a") fmt.Println(set.Contains("a")) fmt.Println(set.Contains("A")) - fmt.Println(set.ContainsI("A")) // Output: // true // false +} + +// ContainsI checks whether a value exists in the set with case-insensitively. +// Note that it internally iterates the whole set to do the comparison with case-insensitively. +func ExampleStrSet_ContainsI() { + var set gset.StrSet + set.Add("a") + fmt.Println(set.ContainsI("a")) + fmt.Println(set.ContainsI("A")) + + // Output: + // true // true } +// Diff returns a new set which is the difference set from `set` to `other`. +// Which means, all the items in `newSet` are in `set` but not in `other`. +func ExampleStrSet_Diff() { + s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true) + s2 := gset.NewStrSetFrom([]string{"a", "b", "c", "d"}, true) + fmt.Println(s2.Diff(s1).Slice()) + + // Output: + // [d] +} + +// Equal checks whether the two sets equal. +func ExampleStrSet_Equal() { + s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true) + s2 := gset.NewStrSetFrom([]string{"a", "b", "c", "d"}, true) + fmt.Println(s2.Equal(s1)) + + s3 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true) + s4 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true) + fmt.Println(s3.Equal(s4)) + + // Output: + // false + // true +} + +// Intersect returns a new set which is the intersection from `set` to `other`. +// Which means, all the items in `newSet` are in `set` and also in `other`. +func ExampleStrSet_Intersect() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c"}...) + var s2 gset.StrSet + s2.Add([]string{"a", "b", "c", "d"}...) + fmt.Println(s2.Intersect(s1).Slice()) + + // May Output: + // [c a b] +} + +// IsSubsetOf checks whether the current set is a sub-set of `other` +func ExampleStrSet_IsSubsetOf() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + var s2 gset.StrSet + s2.Add([]string{"a", "b", "d"}...) + fmt.Println(s2.IsSubsetOf(s1)) + + // Output: + // true +} + +// Iterator iterates the set readonly with given callback function `f`, +// if `f` returns true then continue iterating; or false to stop. +func ExampleStrSet_Iterator() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + s1.Iterator(func(v string) bool { + fmt.Println("Iterator", v) + return true + }) + + // May Output: + // Iterator a + // Iterator b + // Iterator c + // Iterator d +} + +// Join joins items with a string `glue`. +func ExampleStrSet_Join() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + fmt.Println(s1.Join(",")) + + // May Output: + // b,c,d,a +} + +// LockFunc locks writing with callback function `f`. +func ExampleStrSet_LockFunc() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"1", "2"}...) + s1.LockFunc(func(m map[string]struct{}) { + m["3"] = struct{}{} + }) + fmt.Println(s1.Slice()) + + // May Output + // [2 3 1] + +} + +// MarshalJSON implements the interface MarshalJSON for json.Marshal. +func ExampleStrSet_MarshalJSON() { + type Student struct { + Id int + Name string + Scores *gset.StrSet + } + s := Student{ + Id: 1, + Name: "john", + Scores: gset.NewStrSetFrom([]string{"100", "99", "98"}, true), + } + b, _ := json.Marshal(s) + fmt.Println(string(b)) + + // May Output: + // {"Id":1,"Name":"john","Scores":["100","99","98"]} +} + +// Merge adds items from `others` sets into `set`. +func ExampleStrSet_Merge() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + + s2 := gset.NewStrSet(true) + fmt.Println(s1.Merge(s2).Slice()) + + // May Output: + // [d a b c] +} + +// Pops randomly pops an item from set. +func ExampleStrSet_Pop() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + + fmt.Println(s1.Pop()) + + // May Output: + // a +} + +// Pops randomly pops `size` items from set. +// It returns all items if size == -1. +func ExampleStrSet_Pops() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + for _, v := range s1.Pops(2) { + fmt.Println(v) + } + + // May Output: + // a + // b +} + +// RLockFunc locks reading with callback function `f`. +func ExampleStrSet_RLockFunc() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + s1.RLockFunc(func(m map[string]struct{}) { + fmt.Println(m) + }) + + // Output: + // map[a:{} b:{} c:{} d:{}] +} + +// Remove deletes `item` from set. +func ExampleStrSet_Remove() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + s1.Remove("a") + fmt.Println(s1.Slice()) + + // May Output: + // [b c d] +} + +// Size returns the size of the set. +func ExampleStrSet_Size() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + fmt.Println(s1.Size()) + + // Output: + // 4 +} + +// Slice returns the a of items of the set as slice. +func ExampleStrSet_Slice() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + fmt.Println(s1.Slice()) + + // May Output: + // [a,b,c,d] +} + +// String returns items as a string, which implements like json.Marshal does. +func ExampleStrSet_String() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + fmt.Println(s1.String()) + + // May Output: + // "a","b","c","d" +} + +// Sum sums items. Note: The items should be converted to int type, +// or you'd get a result that you unexpected. +func ExampleStrSet_Sum() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"1", "2", "3", "4"}...) + fmt.Println(s1.Sum()) + + // Output: + // 10 +} + +// Union returns a new set which is the union of `set` and `other`. +// Which means, all the items in `newSet` are in `set` or in `other`. +func ExampleStrSet_Union() { + s1 := gset.NewStrSet(true) + s1.Add([]string{"a", "b", "c", "d"}...) + s2 := gset.NewStrSet(true) + s2.Add([]string{"a", "b", "d"}...) + fmt.Println(s1.Union(s2).Slice()) + + // May Output: + // [a b c d] +} + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func ExampleStrSet_UnmarshalJSON() { + b := []byte(`{"Id":1,"Name":"john","Scores":["100","99","98"]}`) + type Student struct { + Id int + Name string + Scores *gset.StrSet + } + s := Student{} + json.Unmarshal(b, &s) + fmt.Println(s) + + // May Output: + // {1 john "99","98","100"} +} + +// UnmarshalValue is an interface implement which sets any type of value for set. +func ExampleStrSet_UnmarshalValue() { + b := []byte(`{"Id":1,"Name":"john","Scores":["100","99","98"]}`) + type Student struct { + Id int + Name string + Scores *gset.StrSet + } + s := Student{} + json.Unmarshal(b, &s) + fmt.Println(s) + + // May Output: + // {1 john "99","98","100"} +} + +// Walk applies a user supplied function `f` to every item of set. func ExampleStrSet_Walk() { var ( set gset.StrSet diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index 9c5a487e4..88b8d55a1 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -642,7 +642,7 @@ func (c *Core) writeSqlToLogger(ctx context.Context, sql *Sql) { } } s := fmt.Sprintf( - "[%3d ms] [%s] [%s:%d] %s%s", + "[%3d ms] [%s] [%s:%-3d] %s%s", sql.End-sql.Start, sql.Group, sqlTypeKey, sql.RowsAffected, transactionIdStr, sql.Format, ) if sql.Error != nil { diff --git a/database/gdb/gdb_func.go b/database/gdb/gdb_func.go index 4c98ff773..d2360309b 100644 --- a/database/gdb/gdb_func.go +++ b/database/gdb/gdb_func.go @@ -829,6 +829,10 @@ func FormatSqlWithArgs(sql string, args []interface{}) string { if args[index] == nil { return "null" } + // Parameters of type Raw do not require special treatment + if v, ok := args[index].(Raw); ok { + return gconv.String(v) + } var ( reflectInfo = utils.OriginValueAndKind(args[index]) ) diff --git a/database/gdb/gdb_model_select.go b/database/gdb/gdb_model_select.go index 6c1445794..70f449d44 100644 --- a/database/gdb/gdb_model_select.go +++ b/database/gdb/gdb_model_select.go @@ -319,32 +319,25 @@ func (m *Model) Scan(pointer interface{}, where ...interface{}) error { // ScanList converts `r` to struct slice which contains other complex struct attributes. // Note that the parameter `listPointer` should be type of *[]struct/*[]*struct. -// Usage example: // -// type Entity struct { -// User *EntityUser -// UserDetail *EntityUserDetail -// UserScores []*EntityUserScores -// } -// var users []*Entity -// or -// var users []Entity -// -// ScanList(&users, "User") -// ScanList(&users, "UserDetail", "User", "uid:Uid") -// ScanList(&users, "UserScores", "User", "uid:Uid") -// The parameters "User"/"UserDetail"/"UserScores" in the example codes specify the target attribute struct -// that current result will be bound to. -// The "uid" in the example codes is the table field name of the result, and the "Uid" is the relational -// struct attribute name. It automatically calculates the HasOne/HasMany relationship with given `relation` -// parameter. -// See the example or unit testing cases for clear understanding for this function. -func (m *Model) ScanList(listPointer interface{}, attributeName string, relation ...string) (err error) { +// See Result.ScanList. +func (m *Model) ScanList(structSlicePointer interface{}, bindToAttrName string, relationAttrNameAndFields ...string) (err error) { result, err := m.All() if err != nil { return err } - return doScanList(m, result, listPointer, attributeName, relation...) + var ( + relationAttrName string + relationFields string + ) + switch len(relationAttrNameAndFields) { + case 2: + relationAttrName = relationAttrNameAndFields[0] + relationFields = relationAttrNameAndFields[1] + case 1: + relationFields = relationAttrNameAndFields[0] + } + return doScanList(m, result, structSlicePointer, bindToAttrName, relationAttrName, relationFields) } // Count does "SELECT COUNT(x) FROM ..." statement for the model. diff --git a/database/gdb/gdb_type_result_scanlist.go b/database/gdb/gdb_type_result_scanlist.go index 6fb16baae..0e76b6c61 100644 --- a/database/gdb/gdb_type_result_scanlist.go +++ b/database/gdb/gdb_type_result_scanlist.go @@ -10,6 +10,7 @@ import ( "database/sql" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/internal/structs" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gutil" @@ -17,21 +18,61 @@ import ( ) // ScanList converts `r` to struct slice which contains other complex struct attributes. -// Note that the parameter `listPointer` should be type of *[]struct/*[]*struct. -// Usage example: +// Note that the parameter `structSlicePointer` should be type of *[]struct/*[]*struct. // +// Usage example 1: Normal attribute struct relation: +// type EntityUser struct { +// Uid int +// Name string +// } +// type EntityUserDetail struct { +// Uid int +// Address string +// } +// type EntityUserScores struct { +// Id int +// Uid int +// Score int +// Course string +// } // type Entity struct { -// User *EntityUser +// User *EntityUser // UserDetail *EntityUserDetail -// UserScores []*EntityUserScores +// UserScores []*EntityUserScores // } // var users []*Entity -// or -// var users []Entity -// // ScanList(&users, "User") +// ScanList(&users, "User", "uid") // ScanList(&users, "UserDetail", "User", "uid:Uid") // ScanList(&users, "UserScores", "User", "uid:Uid") +// ScanList(&users, "UserScores", "User", "uid") +// +// +// Usage example 2: Embedded attribute struct relation: +// type EntityUser struct { +// Uid int +// Name string +// } +// type EntityUserDetail struct { +// Uid int +// Address string +// } +// type EntityUserScores struct { +// Id int +// Uid int +// Score int +// } +// type Entity struct { +// EntityUser +// UserDetail EntityUserDetail +// UserScores []EntityUserScores +// } +// +// var users []*Entity +// ScanList(&users) +// ScanList(&users, "UserDetail", "uid") +// ScanList(&users, "UserScores", "uid") +// // // The parameters "User/UserDetail/UserScores" in the example codes specify the target attribute struct // that current result will be bound to. @@ -42,15 +83,26 @@ import ( // given `relation` parameter. // // See the example or unit testing cases for clear understanding for this function. -func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relationKV ...string) (err error) { - return doScanList(nil, r, listPointer, bindToAttrName, relationKV...) +func (r Result) ScanList(structSlicePointer interface{}, bindToAttrName string, relationAttrNameAndFields ...string) (err error) { + var ( + relationAttrName string + relationFields string + ) + switch len(relationAttrNameAndFields) { + case 2: + relationAttrName = relationAttrNameAndFields[0] + relationFields = relationAttrNameAndFields[1] + case 1: + relationFields = relationAttrNameAndFields[0] + } + return doScanList(nil, r, structSlicePointer, bindToAttrName, relationAttrName, relationFields) } // doScanList converts `result` to struct slice which contains other complex struct attributes recursively. -// The parameter `model` is used for recursively scanning purpose, which means, it can scans the attribute struct/structs recursively but -// it needs the Model for database accessing. -// Note that the parameter `listPointer` should be type of *[]struct/*[]*struct. -func doScanList(model *Model, result Result, listPointer interface{}, bindToAttrName string, relationKV ...string) (err error) { +// The parameter `model` is used for recursively scanning purpose, which means, it can scan the attribute struct/structs recursively, +// but it needs the Model for database accessing. +// Note that the parameter `structSlicePointer` should be type of *[]struct/*[]*struct. +func doScanList(model *Model, result Result, structSlicePointer interface{}, bindToAttrName, relationAttrName, relationFields string) (err error) { if result.IsEmpty() { return nil } @@ -59,8 +111,12 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr return gerror.NewCode(gcode.CodeInvalidParameter, `bindToAttrName should not be empty`) } + if relationAttrName == "." { + relationAttrName = "" + } + var ( - reflectValue = reflect.ValueOf(listPointer) + reflectValue = reflect.ValueOf(structSlicePointer) reflectKind = reflectValue.Kind() ) if reflectKind == reflect.Interface { @@ -70,7 +126,7 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr if reflectKind != reflect.Ptr { return gerror.NewCodef( gcode.CodeInvalidParameter, - "listPointer should be type of *[]struct/*[]*struct, but got: %v", + "structSlicePointer should be type of *[]struct/*[]*struct, but got: %v", reflectKind, ) } @@ -79,7 +135,7 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr if reflectKind != reflect.Slice && reflectKind != reflect.Array { return gerror.NewCodef( gcode.CodeInvalidParameter, - "listPointer should be type of *[]struct/*[]*struct, but got: %v", + "structSlicePointer should be type of *[]struct/*[]*struct, but got: %v", reflectKind, ) } @@ -99,7 +155,7 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr var ( arrayValue reflect.Value // Like: []*Entity arrayItemType reflect.Type // Like: *Entity - reflectType = reflect.TypeOf(listPointer) + reflectType = reflect.TypeOf(structSlicePointer) ) if reflectValue.Len() > 0 { arrayValue = reflectValue @@ -112,46 +168,38 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr // Relation variables. var ( - relationKVStr string - relationDataMap map[string]Value - relationFromAttrName string // Eg: relationKV: User, uid:Uid -> User - relationResultFieldName string // Eg: relationKV: uid:Uid -> uid - relationBindToSubAttrName string // Eg: relationKV: uid:Uid -> Uid + relationDataMap map[string]Value + relationFromFieldName string // Eg: relationKV: id:uid -> id + relationBindToFieldName string // Eg: relationKV: id:uid -> uid ) - if len(relationKV) > 0 { - if len(relationKV) == 1 { - relationKVStr = relationKV[0] - } else { - relationFromAttrName = relationKV[0] - relationKVStr = relationKV[1] - } + if len(relationFields) > 0 { // The relation key string of table filed name and attribute name // can be joined with char '=' or ':'. - array := gstr.SplitAndTrim(relationKVStr, "=") + array := gstr.SplitAndTrim(relationFields, "=") if len(array) == 1 { // Compatible with old splitting char ':'. - array = gstr.SplitAndTrim(relationKVStr, ":") + array = gstr.SplitAndTrim(relationFields, ":") } if len(array) == 1 { // The relation names are the same. - array = []string{relationKVStr, relationKVStr} + array = []string{relationFields, relationFields} } if len(array) == 2 { // Defined table field to relation attribute name. // Like: // uid:Uid // uid:UserId - relationResultFieldName = array[0] - relationBindToSubAttrName = array[1] - if key, _ := gutil.MapPossibleItemByKey(result[0].Map(), relationResultFieldName); key == "" { + relationFromFieldName = array[0] + relationBindToFieldName = array[1] + if key, _ := gutil.MapPossibleItemByKey(result[0].Map(), relationFromFieldName); key == "" { return gerror.NewCodef( gcode.CodeInvalidParameter, - `cannot find possible related table field name "%s" from given relation key "%s"`, - relationResultFieldName, - relationKVStr, + `cannot find possible related table field name "%s" from given relation fields "%s"`, + relationFromFieldName, + relationFields, ) } else { - relationResultFieldName = key + relationFromFieldName = key } } else { return gerror.NewCode( @@ -159,15 +207,15 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr `parameter relationKV should be format of "ResultFieldName:BindToAttrName"`, ) } - if relationResultFieldName != "" { + if relationFromFieldName != "" { // Note that the value might be type of slice. - relationDataMap = result.MapKeyValue(relationResultFieldName) + relationDataMap = result.MapKeyValue(relationFromFieldName) } if len(relationDataMap) == 0 { return gerror.NewCodef( gcode.CodeInvalidParameter, - `cannot find the relation data map, maybe invalid relation given "%v"`, - relationKV, + `cannot find the relation data map, maybe invalid relation fields given "%v"`, + relationFields, ) } } @@ -201,9 +249,9 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr // Bind to relation conditions. var ( - relationFromAttrValue reflect.Value - relationFromAttrField reflect.Value - relationBindToSubAttrNameChecked bool + relationFromAttrValue reflect.Value + relationFromAttrField reflect.Value + relationBindToFieldNameChecked bool ) for i := 0; i < arrayValue.Len(); i++ { arrayElemValue := arrayValue.Index(i) @@ -224,9 +272,9 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr // Like: []Entity } bindToAttrValue = arrayElemValue.FieldByName(bindToAttrName) - if relationFromAttrName != "" { + if relationAttrName != "" { // Attribute value of current slice element. - relationFromAttrValue = arrayElemValue.FieldByName(relationFromAttrName) + relationFromAttrValue = arrayElemValue.FieldByName(relationAttrName) if relationFromAttrValue.Kind() == reflect.Ptr { relationFromAttrValue = relationFromAttrValue.Elem() } @@ -235,36 +283,35 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr relationFromAttrValue = arrayElemValue } if len(relationDataMap) > 0 && !relationFromAttrValue.IsValid() { - return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation specified: "%v"`, relationKV) + return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) } // Check and find possible bind to attribute name. - if relationKVStr != "" && !relationBindToSubAttrNameChecked { - relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName) + if relationFields != "" && !relationBindToFieldNameChecked { + relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) if !relationFromAttrField.IsValid() { var ( - relationFromAttrType = relationFromAttrValue.Type() - filedMap = make(map[string]interface{}) + filedMap, _ = structs.FieldMap(structs.FieldMapInput{ + Pointer: relationFromAttrValue, + RecursiveOption: structs.RecursiveOptionEmbeddedNoTag, + }) ) - for i := 0; i < relationFromAttrType.NumField(); i++ { - filedMap[relationFromAttrType.Field(i).Name] = struct{}{} - } - if key, _ := gutil.MapPossibleItemByKey(filedMap, relationBindToSubAttrName); key == "" { + if key, _ := gutil.MapPossibleItemByKey(gconv.Map(filedMap), relationBindToFieldName); key == "" { return gerror.NewCodef( gcode.CodeInvalidParameter, - `cannot find possible related attribute name "%s" from given relation key "%s"`, - relationBindToSubAttrName, - relationKVStr, + `cannot find possible related attribute name "%s" from given relation fields "%s"`, + relationBindToFieldName, + relationFields, ) } else { - relationBindToSubAttrName = key + relationBindToFieldName = key } } - relationBindToSubAttrNameChecked = true + relationBindToFieldNameChecked = true } switch bindToAttrKind { case reflect.Array, reflect.Slice: if len(relationDataMap) > 0 { - relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName) + relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) if relationFromAttrField.IsValid() { results := make(Result, 0) for _, v := range relationDataMap[gconv.String(relationFromAttrField.Interface())].Slice() { @@ -280,8 +327,8 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr } } } else { - // May be the attribute does not exist yet. - return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation specified: "%v"`, relationKV) + // Maybe the attribute does not exist yet. + return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) } } else { return gerror.NewCodef( @@ -299,7 +346,7 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr element = bindToAttrValue.Elem() } if len(relationDataMap) > 0 { - relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName) + relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) if relationFromAttrField.IsValid() { v := relationDataMap[gconv.String(relationFromAttrField.Interface())] if v == nil { @@ -316,8 +363,8 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr } } } else { - // May be the attribute does not exist yet. - return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation specified: "%v"`, relationKV) + // Maybe the attribute does not exist yet. + return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) } } else { if i >= len(result) { @@ -343,7 +390,7 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr case reflect.Struct: if len(relationDataMap) > 0 { - relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName) + relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) if relationFromAttrField.IsValid() { relationDataItem := relationDataMap[gconv.String(relationFromAttrField.Interface())] if relationDataItem == nil { @@ -360,8 +407,8 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr } } } else { - // May be the attribute does not exist yet. - return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation specified: "%v"`, relationKV) + // Maybe the attribute does not exist yet. + return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) } } else { if i >= len(result) { @@ -388,6 +435,6 @@ func doScanList(model *Model, result Result, listPointer interface{}, bindToAttr return gerror.NewCodef(gcode.CodeInvalidParameter, `unsupported attribute type: %s`, bindToAttrKind.String()) } } - reflect.ValueOf(listPointer).Elem().Set(arrayValue) + reflect.ValueOf(structSlicePointer).Elem().Set(arrayValue) return nil } diff --git a/database/gdb/gdb_z_mysql_association_scanlist_test.go b/database/gdb/gdb_z_mysql_association_scanlist_test.go index b5a908807..dee305cfc 100644 --- a/database/gdb/gdb_z_mysql_association_scanlist_test.go +++ b/database/gdb/gdb_z_mysql_association_scanlist_test.go @@ -1553,7 +1553,7 @@ CREATE TABLE %s ( }) } -func Test_Table_Relation_EmbeddedStruct(t *testing.T) { +func Test_Table_Relation_EmbeddedStruct1(t *testing.T) { var ( tableUser = "user_" + gtime.TimestampMicroStr() tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() @@ -1670,3 +1670,310 @@ CREATE TABLE %s ( t.Assert(scores[24].Address, "address_5") }) } + +func Test_Table_Relation_EmbeddedStruct2(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + // Initialize the data. + gtest.C(t, func(t *gtest.T) { + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "uid": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + t.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + t.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + t.AssertNil(err) + } + } + }) + + // MapKeyValue. + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + t.Assert(all.Len(), 2) + t.Assert(len(all.MapKeyValue("uid")), 2) + t.Assert(all.MapKeyValue("uid")["3"].Map()["uid"], 3) + t.Assert(all.MapKeyValue("uid")["4"].Map()["uid"], 4) + all, err = db.Model(tableUserScores).Where("uid", g.Slice{3, 4}).Order("id asc").All() + t.AssertNil(err) + t.Assert(all.Len(), 10) + t.Assert(len(all.MapKeyValue("uid")), 2) + t.Assert(len(all.MapKeyValue("uid")["3"].Slice()), 5) + t.Assert(len(all.MapKeyValue("uid")["4"].Slice()), 5) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[0])["uid"], 3) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[0])["score"], 1) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[4])["uid"], 3) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[4])["score"], 5) + }) + db.SetDebug(true) + // Result ScanList with struct elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []Entity + // User + err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + // Detail + all, err := db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + // Detail + all, err := db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with struct elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []Entity + // User + err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + // Detail + all, err := db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []*Entity + + // User + err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + // Detail + all, err := db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Model ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + err := db.Model(tableUser). + Where("uid", g.Slice{3, 4}). + Order("uid asc"). + Scan(&users) + t.AssertNil(err) + // Detail + err = db.Model(tableUserDetail). + Where("uid", gdb.ListItemValues(users, "Uid")). + Order("uid asc"). + ScanList(&users, "UserDetail", "uid:Uid") + t.AssertNil(err) + // Scores + err = db.Model(tableUserScores). + Where("uid", gdb.ListItemValues(users, "Uid")). + Order("id asc"). + ScanList(&users, "UserScores", "uid:Uid") + t.AssertNil(err) + + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) +} diff --git a/encoding/gini/gini.go b/encoding/gini/gini.go index 878b6216b..55b5325cf 100644 --- a/encoding/gini/gini.go +++ b/encoding/gini/gini.go @@ -65,7 +65,7 @@ func Decode(data []byte) (res map[string]interface{}, err error) { if strings.Contains(lineStr, "=") && haveSection { values := strings.Split(lineStr, "=") - fieldMap[strings.TrimSpace(values[0])] = strings.TrimSpace(strings.Join(values[1:], "")) + fieldMap[strings.TrimSpace(values[0])] = strings.TrimSpace(strings.Join(values[1:], "=")) res[section] = fieldMap } } diff --git a/encoding/gini/gini_test.go b/encoding/gini/gini_test.go index 1295a0d8a..e080d8900 100644 --- a/encoding/gini/gini_test.go +++ b/encoding/gini/gini_test.go @@ -22,6 +22,7 @@ aa=bb ip = 127.0.0.1 port=9001 enable=true +command=/bin/echo "gf=GoFrame" [DBINFO] type=mysql @@ -40,6 +41,7 @@ func TestDecode(t *testing.T) { } t.Assert(res["addr"].(map[string]interface{})["ip"], "127.0.0.1") t.Assert(res["addr"].(map[string]interface{})["port"], "9001") + t.Assert(res["addr"].(map[string]interface{})["command"], `/bin/echo "gf=GoFrame"`) t.Assert(res["DBINFO"].(map[string]interface{})["user"], "root") t.Assert(res["DBINFO"].(map[string]interface{})["type"], "mysql") t.Assert(res["键"].(map[string]interface{})["呵呵"], "值") diff --git a/os/gcache/gcache_z_example_cache_test.go b/os/gcache/gcache_z_example_cache_test.go new file mode 100644 index 000000000..d28acefba --- /dev/null +++ b/os/gcache/gcache_z_example_cache_test.go @@ -0,0 +1,501 @@ +package gcache_test + +import ( + "fmt" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gcache" + "time" +) + +func ExampleNew() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly. + c := gcache.New() + + // Set cache without expiration + c.Set(ctx, "k1", "v1", 0) + + // Get cache + v, _ := c.Get(ctx, "k1") + fmt.Println(v) + + // Get cache size + n, _ := c.Size(ctx) + fmt.Println(n) + + // Does the specified key name exist in the cache + b, _ := c.Contains(ctx, "k1") + fmt.Println(b) + + // Delete and return the deleted key value + fmt.Println(c.Remove(ctx, "k1")) + + // Close the cache object and let the GC reclaim resources + + c.Close(ctx) + + // Output: + // v1 + // 1 + // true + // v1 +} + +func ExampleCache_Set() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Set cache without expiration + c.Set(ctx, "k1", g.Slice{1, 2, 3, 4, 5, 6, 7, 8, 9}, 0) + + // Get cache + fmt.Println(c.Get(ctx, "k1")) + + // Output: + // [1,2,3,4,5,6,7,8,9] +} + +func ExampleCache_SetAdapters() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // SetAdapter changes the adapter for this cache. Be very note that, this setting function is not concurrent-safe, + // which means you should not call this setting function concurrently in multiple goroutines. + adapter := gcache.New() + c.SetAdapter(adapter) + + // Set cache + c.Set(ctx, "k1", g.Slice{1, 2, 3, 4, 5, 6, 7, 8, 9}, 0) + + // Reverse makes array with elements in reverse order. + fmt.Println(c.Get(ctx, "k1")) + + // Output: + // [1,2,3,4,5,6,7,8,9] +} + +func ExampleCache_SetIfNotExist() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Write when the key name does not exist, and set the expiration time to 1000 milliseconds + k1, err := c.SetIfNotExist(ctx, "k1", "v1", 1000*time.Millisecond) + fmt.Println(k1, err) + + // Returns false when the key name already exists + k2, err := c.SetIfNotExist(ctx, "k1", "v2", 1000*time.Millisecond) + fmt.Println(k2, err) + + // Print the current list of key values + keys1, _ := c.Keys(ctx) + fmt.Println(keys1) + + // It does not expire if `duration` == 0. It deletes the `key` if `duration` < 0 or given `value` is nil. + c.SetIfNotExist(ctx, "k1", 0, -10000) + + // Wait 1 second for K1: V1 to expire automatically + time.Sleep(1200 * time.Millisecond) + + // Print the current key value pair again and find that K1: V1 has expired + keys2, _ := c.Keys(ctx) + fmt.Println(keys2) + + // Output: + // true + // false + // [k1] + // [] +} + +func ExampleCache_SetMap() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // map[interface{}]interface{} + data := g.MapAnyAny{ + "k1": "v1", + "k2": "v2", + "k3": "v3", + } + + // Sets batch sets cache with key-value pairs by `data`, which is expired after `duration`. + // It does not expire if `duration` == 0. It deletes the keys of `data` if `duration` < 0 or given `value` is nil. + c.SetMap(ctx, data, 1000*time.Millisecond) + + // Gets the specified key value + v1, _ := c.Get(ctx, "k1") + v2, _ := c.Get(ctx, "k2") + v3, _ := c.Get(ctx, "k3") + + fmt.Println(v1, v2, v3) + + // Output: + // v1 v2 v3 +} + +func ExampleCache_Size() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Add 10 elements without expiration + for i := 0; i < 10; i++ { + c.Set(ctx, i, i, 0) + } + + // Size returns the number of items in the cache. + n, _ := c.Size(ctx) + fmt.Println(n) + + // Output: + // 10 +} + +func ExampleCache_Update() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Sets batch sets cache with key-value pairs by `data`, which is expired after `duration`. + // It does not expire if `duration` == 0. It deletes the keys of `data` if `duration` < 0 or given `value` is nil. + c.SetMap(ctx, g.MapAnyAny{"k1": "v1", "k2": "v2", "k3": "v3"}, 0) + + // Print the current key value pair + k1, _ := c.Get(ctx, "k1") + fmt.Println(k1) + k2, _ := c.Get(ctx, "k2") + fmt.Println(k2) + k3, _ := c.Get(ctx, "k3") + fmt.Println(k3) + + // Update updates the value of `key` without changing its expiration and returns the old value. + re, exist, _ := c.Update(ctx, "k1", "v11") + fmt.Println(re, exist) + + // The returned value `exist` is false if the `key` does not exist in the cache. + // It does nothing if `key` does not exist in the cache. + re1, exist1, _ := c.Update(ctx, "k4", "v44") + fmt.Println(re1, exist1) + + kup1, _ := c.Get(ctx, "k1") + fmt.Println(kup1) + kup2, _ := c.Get(ctx, "k2") + fmt.Println(kup2) + kup3, _ := c.Get(ctx, "k3") + fmt.Println(kup3) + + // Output: + // v1 + // v2 + // v3 + // v1 true + // false + // v11 + // v2 + // v3 +} + +func ExampleCache_UpdateExpire() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + c.Set(ctx, "k1", "v1", 1000*time.Millisecond) + expire, _ := c.GetExpire(ctx, "k1") + fmt.Println(expire) + + // UpdateExpire updates the expiration of `key` and returns the old expiration duration value. + // It returns -1 and does nothing if the `key` does not exist in the cache. + c.UpdateExpire(ctx, "k1", 500*time.Millisecond) + + expire1, _ := c.GetExpire(ctx, "k1") + fmt.Println(expire1) + + // Output: + // 1s + // 500ms +} + +func ExampleCache_Values() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Write value + c.Set(ctx, "k1", g.Map{"k1": "v1", "k2": "v2"}, 0) + // c.Set(ctx, "k2", "Here is Value2", 0) + // c.Set(ctx, "k3", 111, 0) + + // Values returns all values in the cache as slice. + data, _ := c.Values(ctx) + fmt.Println(data) + + // May Output: + // [map[k1:v1 k2:v2]] +} + +func ExampleCache_Close() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Set Cache + c.Set(ctx, "k1", "v", 0) + data, _ := c.Get(ctx, "k1") + fmt.Println(data) + + // Close closes the cache if necessary. + c.Close(ctx) + + data1, _ := c.Get(ctx, "k1") + + fmt.Println(data1) + + // Output: + // v + // v + +} + +func ExampleCache_Contains() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Set Cache + c.Set(ctx, "k", "v", 0) + + // Contains returns true if `key` exists in the cache, or else returns false. + // return true + data, _ := c.Contains(ctx, "k") + fmt.Println(data) + + // return false + data1, _ := c.Contains(ctx, "k1") + fmt.Println(data1) + + // Output: + // true + // false + +} + +func ExampleCache_Data() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + c.SetMap(ctx, g.MapAnyAny{"k1": "v1", "k2": "v2"}, 0) + c.Set(ctx, "k5", "v5", 0) + + // Get retrieves and returns the associated value of given `key`. + // It returns nil if it does not exist, its value is nil or it's expired. + data, _ := c.Get(ctx, "k1") + fmt.Println(data) + + data1, _ := c.Get(ctx, "k2") + fmt.Println(data1) + + data2, _ := c.Get(ctx, "k5") + fmt.Println(data2) + + // Output: + // v1 + // v2 + // v5 +} + +func ExampleCache_Get() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Set Cache Object + c.Set(ctx, "k1", "v1", 0) + + // Get retrieves and returns the associated value of given `key`. + // It returns nil if it does not exist, its value is nil or it's expired. + data, _ := c.Get(ctx, "k1") + fmt.Println(data) + + // Output: + // v1 +} + +func ExampleCache_GetExpire() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Set cache without expiration + c.Set(ctx, "k", "v", 10000*time.Millisecond) + + // GetExpire retrieves and returns the expiration of `key` in the cache. + // It returns 0 if the `key` does not expire. It returns -1 if the `key` does not exist in the cache. + expire, _ := c.GetExpire(ctx, "k") + fmt.Println(expire) + + // Output: + // 10s +} + +func ExampleCache_GetOrSet() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // GetOrSet retrieves and returns the value of `key`, or sets `key`-`value` pair and returns `value` + // if `key` does not exist in the cache. + data, _ := c.GetOrSet(ctx, "k", "v", 10000*time.Millisecond) + fmt.Println(data) + + data1, _ := c.Get(ctx, "k") + fmt.Println(data1) + + // Output: + // v + // v + +} + +func ExampleCache_GetOrSetFunc() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // GetOrSetFunc retrieves and returns the value of `key`, or sets `key` with result of function `f` + // and returns its result if `key` does not exist in the cache. + c.GetOrSetFunc(ctx, 1, func() (interface{}, error) { + return 111, nil + }, 10000*time.Millisecond) + v, _ := c.Get(ctx, 1) + fmt.Println(v) + + c.GetOrSetFunc(ctx, 2, func() (interface{}, error) { + return nil, nil + }, 10000*time.Millisecond) + v1, _ := c.Get(ctx, 2) + fmt.Println(v1) + + // Output: + // 111 + // +} + +func ExampleCache_GetOrSetFuncLock() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + // Modify locking Note that the function `f` should be executed within writing mutex lock for concurrent safety purpose. + c.GetOrSetFuncLock(ctx, 1, func() (interface{}, error) { + return 11, nil + }, 0) + v, _ := c.Get(ctx, 1) + fmt.Println(v) + + // Modification failed + c.GetOrSetFuncLock(ctx, 1, func() (interface{}, error) { + return 111, nil + }, 0) + v, _ = c.Get(ctx, 1) + fmt.Println(v) + + c.Remove(ctx, g.Slice{1, 2, 3}...) + + // Modify locking + c.GetOrSetFuncLock(ctx, 1, func() (interface{}, error) { + return 111, nil + }, 0) + v, _ = c.Get(ctx, 1) + fmt.Println(v) + + // Modification failed + c.GetOrSetFuncLock(ctx, 1, func() (interface{}, error) { + return 11, nil + }, 0) + v, _ = c.Get(ctx, 1) + fmt.Println(v) + + // Output: + // 11 + // 11 + // 111 + // 111 +} + +func ExampleCache_Keys() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + c.SetMap(ctx, g.MapAnyAny{"k1": "v1"}, 0) + + // Print the current list of key values + keys1, _ := c.Keys(ctx) + fmt.Println(keys1) + + // Output: + // [k1] + +} + +func ExampleCache_Remove() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + c.SetMap(ctx, g.MapAnyAny{"k1": "v1", "k2": "v2"}, 0) + + // Remove deletes one or more keys from cache, and returns its value. + // If multiple keys are given, it returns the value of the last deleted item. + c.Remove(ctx, "k1") + + data, _ := c.Data(ctx) + fmt.Println(data) + + // Output: + // map[k2:v2] +} + +func ExampleCache_Removes() { + + // Create a cache object, + // Of course, you can also easily use the gcache package method directly + c := gcache.New() + + c.SetMap(ctx, g.MapAnyAny{"k1": "v1", "k2": "v2", "k3": "v3", "k4": "v4"}, 0) + + // Remove deletes one or more keys from cache, and returns its value. + // If multiple keys are given, it returns the value of the last deleted item. + c.Removes(ctx, g.Slice{"k1", "k2", "k3"}) + + data, _ := c.Data(ctx) + fmt.Println(data) + + // Output: + // map[k4:v4] +} diff --git a/os/glog/glog_logger.go b/os/glog/glog_logger.go index 79be582b7..bdd873976 100644 --- a/os/glog/glog_logger.go +++ b/os/glog/glog_logger.go @@ -202,7 +202,7 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) { if len(input.Content) > 0 { if input.Content[len(input.Content)-1] == '\n' { // Remove one blank line(\n\n). - if tempStr[0] == '\n' { + if len(tempStr) > 0 && tempStr[0] == '\n' { input.Content += tempStr[1:] } else { input.Content += tempStr diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go new file mode 100644 index 000000000..ecf6128d7 --- /dev/null +++ b/text/gregex/gregex_z_example_test.go @@ -0,0 +1,280 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +package gregex_test + +import ( + "bytes" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/text/gregex" + "strings" +) + +func ExampleIsMatch() { + patternStr := `\d+` + g.Dump(gregex.IsMatch(patternStr, []byte("hello 2022! hello gf!"))) + g.Dump(gregex.IsMatch(patternStr, nil)) + g.Dump(gregex.IsMatch(patternStr, []byte("hello gf!"))) + + // Output: + // true + // false + // false +} + +func ExampleIsMatchString() { + patternStr := `\d+` + g.Dump(gregex.IsMatchString(patternStr, "hello 2022! hello gf!")) + g.Dump(gregex.IsMatchString(patternStr, "hello gf!")) + g.Dump(gregex.IsMatchString(patternStr, "")) + + // Output: + // true + // false + // false +} + +func ExampleMatch() { + patternStr := `(\w+)=(\w+)` + matchStr := "https://goframe.org/pages/viewpage.action?pageId=1114219&searchId=8QC5D1D2E!" + // This method looks for the first match index + result, err := gregex.Match(patternStr, []byte(matchStr)) + g.Dump(result) + g.Dump(err) + + // Output: + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ] + // +} + +func ExampleMatchString() { + patternStr := `(\w+)=(\w+)` + matchStr := "https://goframe.org/pages/viewpage.action?pageId=1114219&searchId=8QC5D1D2E!" + // This method looks for the first match index + result, err := gregex.MatchString(patternStr, matchStr) + g.Dump(result) + g.Dump(err) + + // Output: + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ] + // +} + +func ExampleMatchAll() { + patternStr := `(\w+)=(\w+)` + matchStr := "https://goframe.org/pages/viewpage.action?pageId=1114219&searchId=8QC5D1D2E!" + result, err := gregex.MatchAll(patternStr, []byte(matchStr)) + g.Dump(result) + g.Dump(err) + + // Output: + // [ + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ], + // [ + // "searchId=8QC5D1D2E", + // "searchId", + // "8QC5D1D2E", + // ], + // ] + // +} + +func ExampleMatchAllString() { + patternStr := `(\w+)=(\w+)` + matchStr := "https://goframe.org/pages/viewpage.action?pageId=1114219&searchId=8QC5D1D2E!" + result, err := gregex.MatchAllString(patternStr, matchStr) + g.Dump(result) + g.Dump(err) + + // Output: + // [ + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ], + // [ + // "searchId=8QC5D1D2E", + // "searchId", + // "8QC5D1D2E", + // ], + // ] + // +} + +func ExampleQuote() { + result := gregex.Quote(`[1-9]\d+`) + g.Dump(result) + + // Output: + // "\[1-9\]\\d\+" +} + +func ExampleReplace() { + var ( + patternStr = `\d+` + str = "hello gf 2020!" + repStr = "2021" + result, err = gregex.Replace(patternStr, []byte(repStr), []byte(str)) + ) + g.Dump(err) + g.Dump(result) + + // Output: + // + // "hello gf 2021!" +} + +func ExampleReplaceFunc() { + // In contrast to [ExampleReplaceFunc] + // the result contains the `pattern' of all subpattern that use the matching function + result, err := gregex.ReplaceFuncMatch(`(\d+)~(\d+)`, []byte("hello gf 2018~2020!"), func(match [][]byte) []byte { + g.Dump(match) + match[2] = []byte("2021") + return bytes.Join(match[1:], []byte("~")) + }) + g.Dump(result) + g.Dump(err) + + // Output: + // [ + // "2018~2020", + // "2018", + // "2020", + // ] + // "hello gf 2018~2021!" + // +} + +func ExampleReplaceFuncMatch() { + var ( + patternStr = `(\d+)~(\d+)` + str = "hello gf 2018~2020!" + ) + // In contrast to [ExampleReplaceFunc] + // the result contains the `pattern' of all subpatterns that use the matching function + result, err := gregex.ReplaceFuncMatch(patternStr, []byte(str), func(match [][]byte) []byte { + g.Dump(match) + match[2] = []byte("2021") + return bytes.Join(match[1:], []byte("-")) + }) + g.Dump(result) + g.Dump(err) + + // Output: + // [ + // "2018~2020", + // "2018", + // "2020", + // ] + // "hello gf 2018-2021!" + // +} + +func ExampleReplaceString() { + patternStr := `\d+` + str := "hello gf 2020!" + replaceStr := "2021" + result, err := gregex.ReplaceString(patternStr, replaceStr, str) + + g.Dump(result) + g.Dump(err) + + // Output: + // "hello gf 2021!" + // +} + +func ExampleReplaceStringFunc() { + replaceStrMap := map[string]string{ + "2020": "2021", + } + // When the regular statement can match multiple results + // func can be used to further control the value that needs to be modified + result, err := gregex.ReplaceStringFunc(`\d+`, `hello gf 2018~2020!`, func(b string) string { + g.Dump(b) + if replaceStr, ok := replaceStrMap[b]; ok { + return replaceStr + } + return b + }) + g.Dump(result) + g.Dump(err) + + result, err = gregex.ReplaceStringFunc(`[a-z]*`, "gf@goframe.org", strings.ToUpper) + g.Dump(result) + g.Dump(err) + + // Output: + // "2018" + // "2020" + // "hello gf 2018~2021!" + // + // "GF@GOFRAME.ORG" + // +} + +func ExampleReplaceStringFuncMatch() { + var ( + patternStr = `([A-Z])\w+` + str = "hello Golang 2018~2021!" + ) + // In contrast to [ExampleReplaceFunc] + // the result contains the `pattern' of all subpatterns that use the matching function + result, err := gregex.ReplaceStringFuncMatch(patternStr, str, func(match []string) string { + g.Dump(match) + match[0] = "Gf" + return match[0] + }) + g.Dump(result) + g.Dump(err) + + // Output: + // [ + // "Golang", + // "G", + // ] + // "hello Gf 2018~2021!" + // +} + +func ExampleSplit() { + patternStr := `\d+` + str := "hello2020gf" + result := gregex.Split(patternStr, str) + g.Dump(result) + + // Output: + // [ + // "hello", + // "gf", + // ] +} + +func ExampleValidate() { + // Valid match statement + g.Dump(gregex.Validate(`\d+`)) + // Mismatched statement + g.Dump(gregex.Validate(`[a-9]\d+`)) + + // Output: + // + // { + // Code: "invalid character class range", + // Expr: "a-9", + // } +} diff --git a/util/gconv/gconv_struct.go b/util/gconv/gconv_struct.go index 1ef90525d..1546efae4 100644 --- a/util/gconv/gconv_struct.go +++ b/util/gconv/gconv_struct.go @@ -20,7 +20,7 @@ import ( // Struct maps the params key-value pairs to the corresponding struct object's attributes. // The third parameter `mapping` is unnecessary, indicating the mapping rules between the -// custom key name and the attribute name(case sensitive). +// custom key name and the attribute name(case-sensitive). // // Note: // 1. The `params` can be any type of map/struct, usually a map. diff --git a/util/gutil/gutil_dump.go b/util/gutil/gutil_dump.go index 140209236..06ed56fd5 100644 --- a/util/gutil/gutil_dump.go +++ b/util/gutil/gutil_dump.go @@ -12,6 +12,7 @@ import ( "github.com/gogf/gf/v2/internal/structs" "github.com/gogf/gf/v2/text/gstr" "reflect" + "strings" ) // ExportOption specifies the behavior of function Export. @@ -56,12 +57,17 @@ type doExportOption struct { } func doExport(value interface{}, indent string, buffer *bytes.Buffer, option doExportOption) { + if value == nil { + buffer.WriteString(``) + return + } var ( reflectValue = reflect.ValueOf(value) reflectKind = reflectValue.Kind() - reflectTypeName = reflectValue.Type().String() + reflectTypeName = reflect.TypeOf(value).String() newIndent = indent + dumpIndent ) + reflectTypeName = strings.ReplaceAll(reflectTypeName, `[]uint8`, `[]byte`) if option.WithoutType { reflectTypeName = "" } @@ -73,10 +79,10 @@ func doExport(value interface{}, indent string, buffer *bytes.Buffer, option doE case reflect.Slice, reflect.Array: if _, ok := value.([]byte); ok { if option.WithoutType { - buffer.WriteString(fmt.Sprintf("\"%v\"\n", value)) + buffer.WriteString(fmt.Sprintf(`"%s"`, value)) } else { buffer.WriteString(fmt.Sprintf( - "%s(%d) \"%v\"\n", + `%s(%d) "%s"`, reflectTypeName, len(reflectValue.String()), value, diff --git a/util/gutil/gutil_z_unit_test.go b/util/gutil/gutil_z_unit_test.go index 962f85f91..253b89373 100755 --- a/util/gutil/gutil_z_unit_test.go +++ b/util/gutil/gutil_z_unit_test.go @@ -73,7 +73,7 @@ func Test_Dump(t *testing.T) { }) } -func Test_DumpBrief(t *testing.T) { +func TestDumpWithType(t *testing.T) { type CommonReq struct { AppId int64 `json:"appId" v:"required" in:"path" des:"应用Id" sum:"应用Id Summary"` ResourceId string `json:"resourceId" in:"query" des:"资源Id" sum:"资源Id Summary"` @@ -127,6 +127,7 @@ func Test_DumpBrief(t *testing.T) { 100: 100, }) gutil.DumpWithType(req) + gutil.DumpWithType([][]byte{[]byte("hello")}) }) } diff --git a/util/gvalid/gvalid_validator_check_struct.go b/util/gvalid/gvalid_validator_check_struct.go index 15bddf090..878e8a728 100644 --- a/util/gvalid/gvalid_validator_check_struct.go +++ b/util/gvalid/gvalid_validator_check_struct.go @@ -44,7 +44,7 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error if _, ok := field.TagLookup(noValidationTagName); ok { continue } - if err := v.doCheckStruct(ctx, field.Value); err != nil { + if err = v.doCheckStruct(ctx, field.Value); err != nil { // It merges the errors into single error map. for k, m := range err.(*validationError).errors { errorMaps[k] = m diff --git a/util/gvalid/gvalid_z_example_test.go b/util/gvalid/gvalid_z_example_test.go index bc0c4f0dc..f163b1b56 100644 --- a/util/gvalid/gvalid_z_example_test.go +++ b/util/gvalid/gvalid_z_example_test.go @@ -10,14 +10,13 @@ import ( "context" "errors" "fmt" - "github.com/gogf/gf/v2/os/gctx" - "math" - "reflect" - "github.com/gogf/gf/v2/container/gvar" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gvalid" + "math" + "reflect" ) func ExampleCheckMap() { @@ -276,3 +275,1023 @@ func ExampleValidator_CheckStruct() { // Output: // [map[Type:map[required:请选择用户类型]]] } + +func ExampleValidator_Required() { + type BizReq struct { + ID uint `v:"required"` + Name string `v:"required"` + } + var ( + ctx = context.Background() + req = BizReq{ + ID: 1, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The Name field is required +} + +func ExampleValidator_RequiredIf() { + type BizReq struct { + ID uint `v:"required" dc:"Your ID"` + Name string `v:"required" dc:"Your name"` + Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` + WifeName string `v:"required-if:gender,1"` + HusbandName string `v:"required-if:gender,2"` + } + var ( + ctx = context.Background() + req = BizReq{ + ID: 1, + Name: "test", + Gender: 1, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The WifeName field is required +} + +func ExampleValidator_RequiredUnless() { + type BizReq struct { + ID uint `v:"required" dc:"Your ID"` + Name string `v:"required" dc:"Your name"` + Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` + WifeName string `v:"required-unless:gender,0,gender,2"` + HusbandName string `v:"required-unless:id,0,gender,2"` + } + var ( + ctx = context.Background() + req = BizReq{ + ID: 1, + Name: "test", + Gender: 1, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The WifeName field is required; The HusbandName field is required +} + +func ExampleValidator_RequiredWith() { + type BizReq struct { + ID uint `v:"required" dc:"Your ID"` + Name string `v:"required" dc:"Your name"` + Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` + WifeName string + HusbandName string `v:"required-with:WifeName"` + } + var ( + ctx = context.Background() + req = BizReq{ + ID: 1, + Name: "test", + Gender: 1, + WifeName: "Ann", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The HusbandName field is required +} + +func ExampleValidator_RequiredWithAll() { + type BizReq struct { + ID uint `v:"required" dc:"Your ID"` + Name string `v:"required" dc:"Your name"` + Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` + WifeName string + HusbandName string `v:"required-with-all:Id,Name,Gender,WifeName"` + } + var ( + ctx = context.Background() + req = BizReq{ + ID: 1, + Name: "test", + Gender: 1, + WifeName: "Ann", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The HusbandName field is required +} + +func ExampleValidator_RequiredWithout() { + type BizReq struct { + ID uint `v:"required" dc:"Your ID"` + Name string `v:"required" dc:"Your name"` + Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` + WifeName string + HusbandName string `v:"required-without:Id,WifeName"` + } + var ( + ctx = context.Background() + req = BizReq{ + ID: 1, + Name: "test", + Gender: 1, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The HusbandName field is required +} + +func ExampleValidator_RequiredWithoutAll() { + type BizReq struct { + ID uint `v:"required" dc:"Your ID"` + Name string `v:"required" dc:"Your name"` + Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` + WifeName string + HusbandName string `v:"required-without-all:Id,WifeName"` + } + var ( + ctx = context.Background() + req = BizReq{ + Name: "test", + Gender: 1, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The HusbandName field is required +} + +func ExampleValidator_Date() { + type BizReq struct { + Date1 string `v:"date"` + Date2 string `v:"date"` + Date3 string `v:"date"` + Date4 string `v:"date"` + Date5 string `v:"date"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Date1: "2021-10-31", + Date2: "2021.10.31", + Date3: "2021-Oct-31", + Date4: "2021 Octa 31", + Date5: "2021/Oct/31", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Date3 value is not a valid date; The Date4 value is not a valid date; The Date5 value is not a valid date +} + +func ExampleValidator_Datetime() { + type BizReq struct { + Date1 string `v:"datetime"` + Date2 string `v:"datetime"` + Date3 string `v:"datetime"` + Date4 string `v:"datetime"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Date1: "2021-11-01 23:00:00", + Date2: "2021-11-01 23:00", // error + Date3: "2021/11/01 23:00:00", // error + Date4: "2021/Dec/01 23:00:00", // error + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Date2 value is not a valid datetime; The Date3 value is not a valid datetime; The Date4 value is not a valid datetime +} + +func ExampleValidator_DateFormat() { + type BizReq struct { + Date1 string `v:"date-format:Y-m-d"` + Date2 string `v:"date-format:Y-m-d"` + Date3 string `v:"date-format:Y-m-d H:i:s"` + Date4 string `v:"date-format:Y-m-d H:i:s"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Date1: "2021-11-01", + Date2: "2021-11-01 23:00", // error + Date3: "2021-11-01 23:00:00", + Date4: "2021-11-01 23:00", // error + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Date2 value does not match the format Y-m-d; The Date4 value does not match the format Y-m-d H:i:s +} + +func ExampleValidator_Email() { + type BizReq struct { + MailAddr1 string `v:"email"` + MailAddr2 string `v:"email"` + MailAddr3 string `v:"email"` + MailAddr4 string `v:"email"` + } + + var ( + ctx = context.Background() + req = BizReq{ + MailAddr1: "gf@goframe.org", + MailAddr2: "gf@goframe", // error + MailAddr3: "gf@goframe.org.cn", + MailAddr4: "gf#goframe.org", // error + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The MailAddr2 value must be a valid email address; The MailAddr4 value must be a valid email address +} + +func ExampleValidator_Phone() { + type BizReq struct { + PhoneNumber1 string `v:"phone"` + PhoneNumber2 string `v:"phone"` + PhoneNumber3 string `v:"phone"` + PhoneNumber4 string `v:"phone"` + } + + var ( + ctx = context.Background() + req = BizReq{ + PhoneNumber1: "13578912345", + PhoneNumber2: "11578912345", // error 11x not exist + PhoneNumber3: "17178912345", // error 171 not exit + PhoneNumber4: "1357891234", // error len must be 11 + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The PhoneNumber2 value must be a valid phone number; The PhoneNumber3 value must be a valid phone number; The PhoneNumber4 value must be a valid phone number +} + +func ExampleValidator_PhoneLoose() { + type BizReq struct { + PhoneNumber1 string `v:"phone-loose"` + PhoneNumber2 string `v:"phone-loose"` + PhoneNumber3 string `v:"phone-loose"` + PhoneNumber4 string `v:"phone-loose"` + } + + var ( + ctx = context.Background() + req = BizReq{ + PhoneNumber1: "13578912345", + PhoneNumber2: "11578912345", // error 11x not exist + PhoneNumber3: "17178912345", + PhoneNumber4: "1357891234", // error len must be 11 + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The PhoneNumber2 value must be a valid phone number; The PhoneNumber4 value must be a valid phone number +} + +func ExampleValidator_Telephone() { + type BizReq struct { + Telephone1 string `v:"telephone"` + Telephone2 string `v:"telephone"` + Telephone3 string `v:"telephone"` + Telephone4 string `v:"telephone"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Telephone1: "010-77542145", + Telephone2: "0571-77542145", + Telephone3: "20-77542145", // error + Telephone4: "775421451", // error len must be 7 or 8 + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Telephone3 value must be a valid telephone number; The Telephone4 value must be a valid telephone number +} + +func ExampleValidator_Passport() { + type BizReq struct { + Passport1 string `v:"passport"` + Passport2 string `v:"passport"` + Passport3 string `v:"passport"` + Passport4 string `v:"passport"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Passport1: "goframe", + Passport2: "1356666", // error starting with letter + Passport3: "goframe#", // error containing only numbers or underscores + Passport4: "gf", // error length between 6 and 18 + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Passport2 value is not a valid passport format; The Passport3 value is not a valid passport format; The Passport4 value is not a valid passport format +} + +func ExampleValidator_Password() { + type BizReq struct { + Password1 string `v:"password"` + Password2 string `v:"password"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Password1: "goframe", + Password2: "gofra", // error length between 6 and 18 + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Password2 value is not a valid passport format +} + +func ExampleValidator_Password2() { + type BizReq struct { + Password1 string `v:"password2"` + Password2 string `v:"password2"` + Password3 string `v:"password2"` + Password4 string `v:"password2"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Password1: "Goframe123", + Password2: "gofra", // error length between 6 and 18 + Password3: "Goframe", // error must contain lower and upper letters and numbers. + Password4: "goframe123", // error must contain lower and upper letters and numbers. + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Password2 value is not a valid passport format; The Password3 value is not a valid passport format; The Password4 value is not a valid passport format +} + +func ExampleValidator_Password3() { + type BizReq struct { + Password1 string `v:"password3"` + Password2 string `v:"password3"` + Password3 string `v:"password3"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Password1: "Goframe123#", + Password2: "gofra", // error length between 6 and 18 + Password3: "Goframe123", // error must contain lower and upper letters, numbers and special chars. + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Password2 value is not a valid passport format; The Password3 value is not a valid passport format +} + +func ExampleValidator_Postcode() { + type BizReq struct { + Postcode1 string `v:"postcode"` + Postcode2 string `v:"postcode"` + Postcode3 string `v:"postcode"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Postcode1: "100000", + Postcode2: "10000", // error length must be 6 + Postcode3: "1000000", // error length must be 6 + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Postcode2 value is not a valid passport format; The Postcode3 value is not a valid passport format +} + +func ExampleValidator_ResidentId() { + type BizReq struct { + ResidentID1 string `v:"resident-id"` + } + + var ( + ctx = context.Background() + req = BizReq{ + ResidentID1: "320107199506285482", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The ResidentID1 value is not a valid resident id number +} + +func ExampleValidator_BankCard() { + type BizReq struct { + BankCard1 string `v:"bank-card"` + } + + var ( + ctx = context.Background() + req = BizReq{ + BankCard1: "6225760079930218", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The BankCard1 value must be a valid bank card number +} + +func ExampleValidator_QQ() { + type BizReq struct { + QQ1 string `v:"qq"` + QQ2 string `v:"qq"` + QQ3 string `v:"qq"` + } + + var ( + ctx = context.Background() + req = BizReq{ + QQ1: "389961817", + QQ2: "9999", // error >= 10000 + QQ3: "514258412a", // error all number + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The QQ2 value must be a valid QQ number; The QQ3 value must be a valid QQ number +} + +func ExampleValidator_IP() { + type BizReq struct { + IP1 string `v:"ip"` + IP2 string `v:"ip"` + IP3 string `v:"ip"` + IP4 string `v:"ip"` + } + + var ( + ctx = context.Background() + req = BizReq{ + IP1: "127.0.0.1", + IP2: "fe80::812b:1158:1f43:f0d1", + IP3: "520.255.255.255", // error >= 10000 + IP4: "ze80::812b:1158:1f43:f0d1", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The IP3 value must be a valid IP address; The IP4 value must be a valid IP address +} + +func ExampleValidator_IPV4() { + type BizReq struct { + IP1 string `v:"ipv4"` + IP2 string `v:"ipv4"` + } + + var ( + ctx = context.Background() + req = BizReq{ + IP1: "127.0.0.1", + IP2: "520.255.255.255", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The IP2 value must be a valid IPv4 address +} + +func ExampleValidator_IPV6() { + type BizReq struct { + IP1 string `v:"ipv6"` + IP2 string `v:"ipv6"` + } + + var ( + ctx = context.Background() + req = BizReq{ + IP1: "fe80::812b:1158:1f43:f0d1", + IP2: "ze80::812b:1158:1f43:f0d1", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The IP2 value must be a valid IPv6 address +} + +func ExampleValidator_Mac() { + type BizReq struct { + Mac1 string `v:"mac"` + Mac2 string `v:"mac"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Mac1: "4C-CC-6A-D6-B1-1A", + Mac2: "Z0-CC-6A-D6-B1-1A", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Mac2 value must be a valid MAC address +} + +func ExampleValidator_Url() { + type BizReq struct { + URL1 string `v:"url"` + URL2 string `v:"url"` + URL3 string `v:"url"` + } + + var ( + ctx = context.Background() + req = BizReq{ + URL1: "http://goframe.org", + URL2: "ftp://goframe.org", + URL3: "ws://goframe.org", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The URL3 value must be a valid URL address +} + +func ExampleValidator_Domain() { + type BizReq struct { + Domain1 string `v:"domain"` + Domain2 string `v:"domain"` + Domain3 string `v:"domain"` + Domain4 string `v:"domain"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Domain1: "goframe.org", + Domain2: "a.b", + Domain3: "goframe#org", + Domain4: "1a.2b", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Domain3 value must be a valid domain format; The Domain4 value must be a valid domain format +} + +func ExampleValidator_Size() { + type BizReq struct { + Size1 string `v:"size:10"` + Size2 string `v:"size:5"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Size1: "goframe欢迎你", + Size2: "goframe", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Size2 value length must be 5 +} + +func ExampleValidator_Length() { + type BizReq struct { + Length1 string `v:"length:5,10"` + Length2 string `v:"length:10,15"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Length1: "goframe欢迎你", + Length2: "goframe", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Length2 value length must be between 10 and 15 +} + +func ExampleValidator_MinLength() { + type BizReq struct { + MinLength1 string `v:"min-length:10"` + MinLength2 string `v:"min-length:8"` + } + + var ( + ctx = context.Background() + req = BizReq{ + MinLength1: "goframe欢迎你", + MinLength2: "goframe", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The MinLength2 value length must be equal or greater than 8 +} + +func ExampleValidator_MaxLength() { + type BizReq struct { + MaxLength1 string `v:"max-length:10"` + MaxLength2 string `v:"max-length:5"` + } + + var ( + ctx = context.Background() + req = BizReq{ + MaxLength1: "goframe欢迎你", + MaxLength2: "goframe", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The MaxLength2 value length must be equal or lesser than 5 +} + +func ExampleValidator_Between() { + type BizReq struct { + Age1 int `v:"between:1,100"` + Age2 int `v:"between:1,100"` + Score1 float32 `v:"between:0.0,10.0"` + Score2 float32 `v:"between:0.0,10.0"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Age1: 50, + Age2: 101, + Score1: 9.8, + Score2: -0.5, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Age2 value must be between 1 and 100; The Score2 value must be between 0 and 10 +} + +func ExampleValidator_Min() { + type BizReq struct { + Age1 int `v:"min:100"` + Age2 int `v:"min:100"` + Score1 float32 `v:"min:10.0"` + Score2 float32 `v:"min:10.0"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Age1: 50, + Age2: 101, + Score1: 9.8, + Score2: 10.1, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Age1 value must be equal or greater than 100; The Score1 value must be equal or greater than 10 +} + +func ExampleValidator_Max() { + type BizReq struct { + Age1 int `v:"max:100"` + Age2 int `v:"max:100"` + Score1 float32 `v:"max:10.0"` + Score2 float32 `v:"max:10.0"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Age1: 99, + Age2: 101, + Score1: 9.9, + Score2: 10.1, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Age2 value must be equal or lesser than 100; The Score2 value must be equal or lesser than 10 +} + +func ExampleValidator_Json() { + type BizReq struct { + JSON1 string `v:"json"` + JSON2 string `v:"json"` + } + + var ( + ctx = context.Background() + req = BizReq{ + JSON1: "{\"name\":\"goframe\",\"author\":\"郭强\"}", + JSON2: "{\"name\":\"goframe\",\"author\":\"郭强\",\"test\"}", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The JSON2 value must be a valid JSON string +} + +func ExampleValidator_Integer() { + type BizReq struct { + Integer string `v:"integer"` + Float string `v:"integer"` + Str string `v:"integer"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Integer: "100", + Float: "10.0", + Str: "goframe", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Float value must be an integer; The Str value must be an integer +} + +func ExampleValidator_Float() { + type BizReq struct { + Integer string `v:"float"` + Float string `v:"float"` + Str string `v:"float"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Integer: "100", + Float: "10.0", + Str: "goframe", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Str value must be a float +} + +func ExampleValidator_Boolean() { + type BizReq struct { + Boolean bool `v:"boolean"` + Integer int `v:"boolean"` + Float float32 `v:"boolean"` + Str1 string `v:"boolean"` + Str2 string `v:"boolean"` + Str3 string `v:"boolean"` + } + + var ( + ctx = context.Background() + req = BizReq{ + Boolean: true, + Integer: 1, + Float: 10.0, + Str1: "on", + Str2: "", + Str3: "goframe", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Print(err) + } + + // Output: + // The Float value field must be true or false; The Str3 value field must be true or false +} + +func ExampleValidator_Same() { + type BizReq struct { + Name string `v:"required"` + Password string `v:"required|same:Password2"` + Password2 string `v:"required"` + } + var ( + ctx = context.Background() + req = BizReq{ + Name: "gf", + Password: "goframe.org", + Password2: "goframe.net", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The Password value must be the same as field Password2 +} + +func ExampleValidator_Different() { + type BizReq struct { + Name string `v:"required"` + MailAddr string `v:"required"` + OtherMailAddr string `v:"required|different:MailAddr"` + } + var ( + ctx = context.Background() + req = BizReq{ + Name: "gf", + MailAddr: "gf@goframe.org", + OtherMailAddr: "gf@goframe.org", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The OtherMailAddr value must be different from field MailAddr +} + +func ExampleValidator_In() { + type BizReq struct { + ID uint `v:"required" dc:"Your Id"` + Name string `v:"required" dc:"Your name"` + Gender uint `v:"in:0,1,2" dc:"0:Secret;1:Male;2:Female"` + } + var ( + ctx = context.Background() + req = BizReq{ + ID: 1, + Name: "test", + Gender: 3, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The Gender value is not in acceptable range +} + +func ExampleValidator_NotIn() { + type BizReq struct { + ID uint `v:"required" dc:"Your Id"` + Name string `v:"required" dc:"Your name"` + InvalidIndex uint `v:"not-in:-1,0,1"` + } + var ( + ctx = context.Background() + req = BizReq{ + ID: 1, + Name: "test", + InvalidIndex: 1, + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The InvalidIndex value is not in acceptable range +} + +func ExampleValidator_Regex() { + type BizReq struct { + Regex1 string `v:"regex:[1-9][0-9]{4,14}"` + Regex2 string `v:"regex:[1-9][0-9]{4,14}"` + Regex3 string `v:"regex:[1-9][0-9]{4,14}"` + } + var ( + ctx = context.Background() + req = BizReq{ + Regex1: "1234", + Regex2: "01234", + Regex3: "10000", + } + ) + if err := g.Validator().CheckStruct(ctx, req); err != nil { + fmt.Println(err) + } + + // Output: + // The Regex1 value is invalid; The Regex2 value is invalid +}