From 183d800f4cf5a5083003a51092972bbfea826dc1 Mon Sep 17 00:00:00 2001 From: daguang Date: Mon, 1 Nov 2021 12:17:53 +0800 Subject: [PATCH 01/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 67 ++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 text/gregex/gregex_z_example_test.go diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go new file mode 100644 index 000000000..8c5ea8e74 --- /dev/null +++ b/text/gregex/gregex_z_example_test.go @@ -0,0 +1,67 @@ +// 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 + +func ExampleIsMatch() { + +} + +func ExampleIsMatchString() { + +} + +func ExampleMatch() { + +} + +func ExampleMatchAll() { + +} + +func ExampleMatchAllString() { + +} + +func ExampleMatchString() { + +} + +func ExampleQuote() { + +} + +func ExampleReplace() { + +} + +func ExampleReplaceFunc() { + +} + +func ExampleReplaceFuncMatch() { + +} + +func ExampleReplaceString() { + +} + +func ExampleReplaceStringFunc() { + +} + +func ExampleReplaceStringFuncMatch() { + +} + +func ExampleSplit() { + +} + +func ExampleValidate() { + +} From 6c3aa6ede51deb577347768ced2d4cc76044284a Mon Sep 17 00:00:00 2001 From: daguang Date: Tue, 2 Nov 2021 20:08:15 +0800 Subject: [PATCH 02/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 174 ++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 2 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index 8c5ea8e74..a4590ea63 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -3,65 +3,235 @@ // 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 -func ExampleIsMatch() { +import ( + "fmt" + "github.com/gogf/gf/v2/text/gregex" +) +func ExampleIsMatch() { + var str = "hello 94 easy gf!" + patternStr := `[1-9]\d*` + fmt.Println(gregex.IsMatch(patternStr, []byte(str))) + + // output + // true } func ExampleIsMatchString() { + var str = "hello 94 easy gf!" + patternStr := `[1-9]\d*` + fmt.Println(gregex.IsMatchString(patternStr, str)) + // output + // true } func ExampleMatch() { + var str = "hello 94 easy gf!" + patternStr := `[1-9]\d*` + result, err := gregex.Match(patternStr, []byte(str)) + if err != nil { + fmt.Println(err.Error()) + } + for _, v := range result { + fmt.Println(string(v)) + } + // output + // 94 } func ExampleMatchAll() { + var str = "hello 94 easy gf!" + patternStr := `[1-9]\d*` + results, err := gregex.MatchAll(patternStr, []byte(str)) + if err != nil { + fmt.Println(err.Error()) + } + for _, result := range results { + for _, v := range result { + fmt.Println(string(v)) + } + } + // output + // 94 } func ExampleMatchAllString() { + var str = "hello 94 easy gf!" + patternStr := `[1-9]\d*` + results, err := gregex.MatchAllString(patternStr, str) + if err != nil { + fmt.Println(err.Error()) + } + for _, result := range results { + for _, v := range result { + fmt.Println(v) + } + } + // output + // 94 } func ExampleMatchString() { + var str = "hello 94 easy gf!" + patternStr := `[1-9]\d*` + results, err := gregex.MatchString(patternStr, str) + if err != nil { + fmt.Println(err.Error()) + } + for _, result := range results { + fmt.Println(result) + } + // output + // 94 } func ExampleQuote() { + patternStr := `[1-9]\d*` + result := gregex.Quote(patternStr) + fmt.Println(result) + // output + // \[1-9\]\\d\* } func ExampleReplace() { + patternStr := `[1-9]\d*` + str := "hello gf 2020!" + repStr := "2021" + result, err := gregex.Replace(patternStr, []byte(repStr), []byte(str)) + if err != nil { + fmt.Println(err.Error()) + } + fmt.Println(string(result)) + // output + // hello gf 2021! } func ExampleReplaceFunc() { + patternStr := `[1-9]\d*` + str := "hello gf 2020!" + result, err := gregex.ReplaceFunc(patternStr, []byte(str), func(b []byte) []byte { + replaceStr := "2021" + if string(b) == "2020" { + return []byte(replaceStr) + } + return nil + }) + if err != nil { + fmt.Println(err.Error()) + } + fmt.Println(string(result)) + // output + // hello gf 2021! } func ExampleReplaceFuncMatch() { + patternStr := `[1-9]\d*` + str := "hello gf 2020!" + result, err := gregex.ReplaceFuncMatch(patternStr, []byte(str), func(match [][]byte) []byte { + replaceStr := "2021" + for _, v := range match { + if string(v) == "2020" { + return []byte(replaceStr) + } + } + return nil + }) + if err != nil { + fmt.Println(err.Error()) + } + fmt.Println(string(result)) + // output + // hello gf 2021! } func ExampleReplaceString() { + patternStr := `[1-9]\d*` + str := "hello gf 2020!" + replaceStr := "2021" + result, err := gregex.ReplaceString(patternStr, replaceStr, str) + if err != nil { + fmt.Println(result) + } + fmt.Println(result) + // output + // hello gf 2021! } func ExampleReplaceStringFunc() { + patternStr := `[1-9]\d*` + str := "hello gf 2020!" + result, err := gregex.ReplaceStringFunc(patternStr, str, func(s string) string { + replaceStr := "2021" + if s == "2020" { + return replaceStr + } + return "" + }) + if err != nil { + fmt.Println(result) + } + fmt.Println(result) + // output + // hello gf 2021! } func ExampleReplaceStringFuncMatch() { + patternStr := `[1-9]\d*` + str := "hello gf 2020!" + result, err := gregex.ReplaceStringFuncMatch(patternStr, str, func(match []string) string { + replaceStr := "2021" + for _, v := range match { + if v == "2020" { + return replaceStr + } + } + return "" + }) + if err != nil { + fmt.Println(result) + } + fmt.Println(result) + // output + // hello gf 2021! } func ExampleSplit() { + patternStr := `[1-9]\d*` + str := "hello2020gf" + result := gregex.Split(patternStr, str) + for _, v := range result { + fmt.Println(v) + } + // output + // hello + // gf } func ExampleValidate() { + patternStr := `[1-9]\d*` + err := gregex.Validate(patternStr) + if err != nil { + fmt.Println(err) + } + if err == nil { + fmt.Println("ok") + } + // output + // ok } From d980cff6637b8bc0ca556409fc273d46c56906c6 Mon Sep 17 00:00:00 2001 From: daguang Date: Wed, 3 Nov 2021 11:22:17 +0800 Subject: [PATCH 03/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 182 ++++++++++++++++----------- 1 file changed, 107 insertions(+), 75 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index a4590ea63..4e2e7470d 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -7,6 +7,7 @@ package gregex_test import ( "fmt" + "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/text/gregex" ) @@ -35,11 +36,11 @@ func ExampleMatch() { if err != nil { fmt.Println(err.Error()) } - for _, v := range result { - fmt.Println(string(v)) - } + g.Dump(result) + g.Dump(result[0]) // output + // ["OTQ="] // 94 } @@ -50,46 +51,41 @@ func ExampleMatchAll() { if err != nil { fmt.Println(err.Error()) } - for _, result := range results { - for _, v := range result { - fmt.Println(string(v)) - } - } + g.Dump(results) // output - // 94 + // [["OTQ="]] + // } func ExampleMatchAllString() { - var str = "hello 94 easy gf!" + var str = "hello 94 98 easy gf!" patternStr := `[1-9]\d*` results, err := gregex.MatchAllString(patternStr, str) if err != nil { fmt.Println(err.Error()) } - for _, result := range results { - for _, v := range result { - fmt.Println(v) - } - } + + g.Dump(results) // output - // 94 + // [["94"],["98"]] } func ExampleMatchString() { - var str = "hello 94 easy gf!" + var str = "hello 94 98 easy gf!" patternStr := `[1-9]\d*` + + // if you need a greed match, should use <..all> methods results, err := gregex.MatchString(patternStr, str) if err != nil { fmt.Println(err.Error()) } - for _, result := range results { - fmt.Println(result) - } + + g.Dump(results) // output - // 94 + // ["94"] } func ExampleQuote() { @@ -106,53 +102,75 @@ func ExampleReplace() { str := "hello gf 2020!" repStr := "2021" result, err := gregex.Replace(patternStr, []byte(repStr), []byte(str)) - if err != nil { - fmt.Println(err.Error()) - } - fmt.Println(string(result)) + + g.Dump(err) + g.Dump(result) // output + // null // hello gf 2021! } func ExampleReplaceFunc() { patternStr := `[1-9]\d*` - str := "hello gf 2020!" + str := "hello gf 2018~2020!" + + // 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.ReplaceFunc(patternStr, []byte(str), func(b []byte) []byte { + + g.Dump(b) + replaceStr := "2021" if string(b) == "2020" { return []byte(replaceStr) } - return nil + return b }) - if err != nil { - fmt.Println(err.Error()) - } - fmt.Println(string(result)) + + g.Dump(result) + g.Dump(err) // output - // hello gf 2021! + // 2018 + // 2020 + // hello gf 2018~2021! + // null } func ExampleReplaceFuncMatch() { patternStr := `[1-9]\d*` - str := "hello gf 2020!" + 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) + replaceStr := "2021" for _, v := range match { if string(v) == "2020" { return []byte(replaceStr) } } - return nil + return match[0] }) - if err != nil { - fmt.Println(err.Error()) - } - fmt.Println(string(result)) + + g.Dump(result) + g.Dump(err) // output - // hello gf 2021! + // [ + // "MjAxOA==" + // ] + // + // [ + // "MjAyMA==" + // ] + // + // hello gf 2018~2021! + // null } func ExampleReplaceString() { @@ -160,78 +178,92 @@ func ExampleReplaceString() { str := "hello gf 2020!" replaceStr := "2021" result, err := gregex.ReplaceString(patternStr, replaceStr, str) - if err != nil { - fmt.Println(result) - } - fmt.Println(result) + + g.Dump(result) + g.Dump(err) // output // hello gf 2021! + // null } func ExampleReplaceStringFunc() { patternStr := `[1-9]\d*` - str := "hello gf 2020!" - result, err := gregex.ReplaceStringFunc(patternStr, str, func(s string) string { + str := "hello gf 2018~2020!" + + // 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(patternStr, str, func(b string) string { + + g.Dump(b) + replaceStr := "2021" - if s == "2020" { + if b == "2020" { return replaceStr } - return "" + return b }) - if err != nil { - fmt.Println(result) - } - fmt.Println(result) + + g.Dump(result) + g.Dump(err) // output - // hello gf 2021! + // 2018 + // 2020 + // hello gf 2018~2021! + // null } func ExampleReplaceStringFuncMatch() { patternStr := `[1-9]\d*` - str := "hello gf 2020!" - result, err := gregex.ReplaceStringFuncMatch(patternStr, str, func(match []string) string { + str := "hello gf 2018~2020!" + + // 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.ReplaceStringFuncMatch(patternStr, str, func(b []string) string { + + g.Dump(b) + replaceStr := "2021" - for _, v := range match { + for _, v := range b { if v == "2020" { return replaceStr } } - return "" + return b[0] }) - if err != nil { - fmt.Println(result) - } - fmt.Println(result) + + g.Dump(result) + g.Dump(err) // output - // hello gf 2021! + // ["2018"] + // ["2020"] + // hello gf 2018~2021! + // null } func ExampleSplit() { patternStr := `[1-9]\d*` str := "hello2020gf" result := gregex.Split(patternStr, str) - for _, v := range result { - fmt.Println(v) - } + + g.Dump(result) // output - // hello - // gf + // ["hello","gf"] } func ExampleValidate() { - patternStr := `[1-9]\d*` - err := gregex.Validate(patternStr) - if err != nil { - fmt.Println(err) - } - if err == nil { - fmt.Println("ok") - } + // Valid match statement + g.Dump(gregex.Validate(`[1-9]\d*`)) + // Mismatched statement + g.Dump(gregex.Validate(`[a-9]\d*`)) // output - // ok + // null + // { + // "Code": "invalid character class range", + // "Expr": "a-9" + // } } From 6b9f72d97336a0bcc035e6251de6e242d90f35f9 Mon Sep 17 00:00:00 2001 From: daguang Date: Wed, 3 Nov 2021 11:28:54 +0800 Subject: [PATCH 04/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 89 +++++++++++++++++++--------- 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index 4e2e7470d..3ab980f63 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -6,70 +6,101 @@ package gregex_test import ( - "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/text/gregex" ) func ExampleIsMatch() { - var str = "hello 94 easy gf!" patternStr := `[1-9]\d*` - fmt.Println(gregex.IsMatch(patternStr, []byte(str))) + g.Dump(gregex.IsMatch(patternStr, []byte("hello 94 easy gf!"))) + g.Dump(gregex.IsMatch(patternStr, nil)) + g.Dump(gregex.IsMatch(patternStr, []byte("hello easy gf!"))) // output // true + // false + // false } func ExampleIsMatchString() { - var str = "hello 94 easy gf!" patternStr := `[1-9]\d*` - fmt.Println(gregex.IsMatchString(patternStr, str)) + g.Dump(gregex.IsMatchString(patternStr, "hello 94 easy gf!")) + g.Dump(gregex.IsMatchString(patternStr, "hello easy gf!")) + g.Dump(gregex.IsMatchString(patternStr, "")) // output // true + // false + // false } func ExampleMatch() { - var str = "hello 94 easy gf!" patternStr := `[1-9]\d*` - result, err := gregex.Match(patternStr, []byte(str)) - if err != nil { - fmt.Println(err.Error()) - } + result, err := gregex.Match(patternStr, []byte("hello 94 98 easy gf!")) g.Dump(result) - g.Dump(result[0]) + g.Dump(err) + + result, err = gregex.Match(patternStr, nil) + g.Dump(result) + g.Dump(err) + + result, err = gregex.Match(patternStr, []byte("hello easy gf!")) + g.Dump(result) + g.Dump(err) // output // ["OTQ="] - // 94 + // null + // [] + // null + // [] + // null } func ExampleMatchAll() { - var str = "hello 94 easy gf!" patternStr := `[1-9]\d*` - results, err := gregex.MatchAll(patternStr, []byte(str)) - if err != nil { - fmt.Println(err.Error()) - } + results, err := gregex.MatchAll(patternStr, []byte("hello 94 98 easy gf!")) g.Dump(results) + g.Dump(err) + + results, err = gregex.MatchAll(patternStr, []byte("hello easy gf!")) + g.Dump(results) + g.Dump(err) + + results, err = gregex.MatchAll(patternStr, nil) + g.Dump(results) + g.Dump(err) // output - // [["OTQ="]] - // + // [["OTQ="],["OTg="]] + // null + // [] + // null + // [] + // null } func ExampleMatchAllString() { - var str = "hello 94 98 easy gf!" patternStr := `[1-9]\d*` - results, err := gregex.MatchAllString(patternStr, str) - if err != nil { - fmt.Println(err.Error()) - } - + results, err := gregex.MatchAllString(patternStr, "hello 94 98 easy gf!") g.Dump(results) + g.Dump(err) + + results, err = gregex.MatchAllString(patternStr, "hello easy gf!") + g.Dump(results) + g.Dump(err) + + results, err = gregex.MatchAllString(patternStr, "") + g.Dump(results) + g.Dump(err) // output // [["94"],["98"]] + // null + // [] + // null + // [] + // null } func ExampleMatchString() { @@ -78,20 +109,20 @@ func ExampleMatchString() { // if you need a greed match, should use <..all> methods results, err := gregex.MatchString(patternStr, str) - if err != nil { - fmt.Println(err.Error()) - } g.Dump(results) + g.Dump(err) // output // ["94"] + // null } func ExampleQuote() { patternStr := `[1-9]\d*` result := gregex.Quote(patternStr) - fmt.Println(result) + + g.Dump(result) // output // \[1-9\]\\d\* From 205243e8b927d55953ca67537d068506c158330a Mon Sep 17 00:00:00 2001 From: daguang Date: Thu, 4 Nov 2021 21:02:54 +0800 Subject: [PATCH 05/22] update --- text/gregex/gregex_z_example_test.go | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index 3ab980f63..b55e58be1 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -16,7 +16,7 @@ func ExampleIsMatch() { g.Dump(gregex.IsMatch(patternStr, nil)) g.Dump(gregex.IsMatch(patternStr, []byte("hello easy gf!"))) - // output + // Output // true // false // false @@ -28,7 +28,7 @@ func ExampleIsMatchString() { g.Dump(gregex.IsMatchString(patternStr, "hello easy gf!")) g.Dump(gregex.IsMatchString(patternStr, "")) - // output + // Output // true // false // false @@ -48,7 +48,7 @@ func ExampleMatch() { g.Dump(result) g.Dump(err) - // output + // Output // ["OTQ="] // null // [] @@ -71,7 +71,7 @@ func ExampleMatchAll() { g.Dump(results) g.Dump(err) - // output + // Output // [["OTQ="],["OTg="]] // null // [] @@ -94,7 +94,7 @@ func ExampleMatchAllString() { g.Dump(results) g.Dump(err) - // output + // Output // [["94"],["98"]] // null // [] @@ -113,7 +113,7 @@ func ExampleMatchString() { g.Dump(results) g.Dump(err) - // output + // Output // ["94"] // null } @@ -124,7 +124,7 @@ func ExampleQuote() { g.Dump(result) - // output + // Output // \[1-9\]\\d\* } @@ -137,7 +137,7 @@ func ExampleReplace() { g.Dump(err) g.Dump(result) - // output + // Output // null // hello gf 2021! } @@ -162,7 +162,7 @@ func ExampleReplaceFunc() { g.Dump(result) g.Dump(err) - // output + // Output // 2018 // 2020 // hello gf 2018~2021! @@ -191,7 +191,7 @@ func ExampleReplaceFuncMatch() { g.Dump(result) g.Dump(err) - // output + // Output // [ // "MjAxOA==" // ] @@ -213,7 +213,7 @@ func ExampleReplaceString() { g.Dump(result) g.Dump(err) - // output + // Output // hello gf 2021! // null } @@ -238,7 +238,7 @@ func ExampleReplaceStringFunc() { g.Dump(result) g.Dump(err) - // output + // Output // 2018 // 2020 // hello gf 2018~2021! @@ -267,7 +267,7 @@ func ExampleReplaceStringFuncMatch() { g.Dump(result) g.Dump(err) - // output + // Output // ["2018"] // ["2020"] // hello gf 2018~2021! @@ -281,7 +281,7 @@ func ExampleSplit() { g.Dump(result) - // output + // Output // ["hello","gf"] } @@ -291,7 +291,7 @@ func ExampleValidate() { // Mismatched statement g.Dump(gregex.Validate(`[a-9]\d*`)) - // output + // Output // null // { // "Code": "invalid character class range", From 2a2bb4f1e1cc0f4e25cd55905ae70261bc4c8c2f Mon Sep 17 00:00:00 2001 From: daguang Date: Thu, 4 Nov 2021 21:39:28 +0800 Subject: [PATCH 06/22] improve the example document --- text/gregex/gregex_z_example_test.go | 291 +++++++++++++-------------- 1 file changed, 144 insertions(+), 147 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index b55e58be1..d4196470d 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -11,10 +11,10 @@ import ( ) func ExampleIsMatch() { - patternStr := `[1-9]\d*` - g.Dump(gregex.IsMatch(patternStr, []byte("hello 94 easy gf!"))) + patternStr := `[1-9]\d+` + g.Dump(gregex.IsMatch(patternStr, []byte("hello 2022! hello gf!"))) g.Dump(gregex.IsMatch(patternStr, nil)) - g.Dump(gregex.IsMatch(patternStr, []byte("hello easy gf!"))) + g.Dump(gregex.IsMatch(patternStr, []byte("hello gf!"))) // Output // true @@ -23,9 +23,9 @@ func ExampleIsMatch() { } func ExampleIsMatchString() { - patternStr := `[1-9]\d*` - g.Dump(gregex.IsMatchString(patternStr, "hello 94 easy gf!")) - g.Dump(gregex.IsMatchString(patternStr, "hello easy gf!")) + patternStr := `[1-9]\d+` + g.Dump(gregex.IsMatchString(patternStr, "hello 2022! hello gf!")) + g.Dump(gregex.IsMatchString(patternStr, "hello gf!")) g.Dump(gregex.IsMatchString(patternStr, "")) // Output @@ -35,8 +35,8 @@ func ExampleIsMatchString() { } func ExampleMatch() { - patternStr := `[1-9]\d*` - result, err := gregex.Match(patternStr, []byte("hello 94 98 easy gf!")) + patternStr := `[1-9]\d+` + result, err := gregex.Match(patternStr, []byte("hello 2022! hello gf!")) g.Dump(result) g.Dump(err) @@ -49,21 +49,21 @@ func ExampleMatch() { g.Dump(err) // Output - // ["OTQ="] - // null + // ["2022"] + // // [] - // null + // // [] - // null + // } func ExampleMatchAll() { - patternStr := `[1-9]\d*` - results, err := gregex.MatchAll(patternStr, []byte("hello 94 98 easy gf!")) + patternStr := `[1-9]\d+` + results, err := gregex.MatchAll(patternStr, []byte("goodBye 2021! hello 2022! hello gf!")) g.Dump(results) g.Dump(err) - results, err = gregex.MatchAll(patternStr, []byte("hello easy gf!")) + results, err = gregex.MatchAll(patternStr, []byte("hello gf!")) g.Dump(results) g.Dump(err) @@ -72,21 +72,21 @@ func ExampleMatchAll() { g.Dump(err) // Output - // [["OTQ="],["OTg="]] - // null + // [["2021"],["2022"]] + // // [] - // null + // // [] - // null + // } func ExampleMatchAllString() { - patternStr := `[1-9]\d*` - results, err := gregex.MatchAllString(patternStr, "hello 94 98 easy gf!") + patternStr := `[1-9]\d+` + results, err := gregex.MatchAllString(patternStr, "goodBye 2021! hello 2022! hello gf!") g.Dump(results) g.Dump(err) - results, err = gregex.MatchAllString(patternStr, "hello easy gf!") + results, err = gregex.MatchAllString(patternStr, "hello gf!") g.Dump(results) g.Dump(err) @@ -95,18 +95,17 @@ func ExampleMatchAllString() { g.Dump(err) // Output - // [["94"],["98"]] - // null + // [["2021"],["2022"]] + // // [] - // null + // // [] - // null + // } func ExampleMatchString() { - var str = "hello 94 98 easy gf!" - patternStr := `[1-9]\d*` - + var str = "goodBye 2021! hello 2022! hello gf!" + patternStr := `[1-9]\d+` // if you need a greed match, should use <..all> methods results, err := gregex.MatchString(patternStr, str) @@ -114,122 +113,50 @@ func ExampleMatchString() { g.Dump(err) // Output - // ["94"] - // null + // ["2021"] + // } func ExampleQuote() { - patternStr := `[1-9]\d*` + patternStr := `[1-9]\d+` result := gregex.Quote(patternStr) g.Dump(result) // Output - // \[1-9\]\\d\* + // "\[1-9\]\\d\+" } func ExampleReplace() { - patternStr := `[1-9]\d*` - str := "hello gf 2020!" - repStr := "2021" - result, err := gregex.Replace(patternStr, []byte(repStr), []byte(str)) + var ( + patternStr = `[1-9]\d+` + str = "hello gf 2020!" + repStr = "2021" + result, err = gregex.Replace(patternStr, []byte(repStr), []byte(str)) + ) g.Dump(err) g.Dump(result) // Output - // null - // hello gf 2021! + // + // "hello gf 2021!" } func ExampleReplaceFunc() { - patternStr := `[1-9]\d*` - str := "hello gf 2018~2020!" + var ( + patternStr = `[1-9]\d+` + str = "hello gf 2018~2020!" + replaceStrMap = map[string][]byte{ + "2020": []byte("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.ReplaceFunc(patternStr, []byte(str), func(b []byte) []byte { - g.Dump(b) - - replaceStr := "2021" - if string(b) == "2020" { - return []byte(replaceStr) - } - return b - }) - - g.Dump(result) - g.Dump(err) - - // Output - // 2018 - // 2020 - // hello gf 2018~2021! - // null -} - -func ExampleReplaceFuncMatch() { - patternStr := `[1-9]\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) - - replaceStr := "2021" - for _, v := range match { - if string(v) == "2020" { - return []byte(replaceStr) - } - } - return match[0] - }) - - g.Dump(result) - g.Dump(err) - - // Output - // [ - // "MjAxOA==" - // ] - // - // [ - // "MjAyMA==" - // ] - // - // hello gf 2018~2021! - // null -} - -func ExampleReplaceString() { - patternStr := `[1-9]\d*` - str := "hello gf 2020!" - replaceStr := "2021" - result, err := gregex.ReplaceString(patternStr, replaceStr, str) - - g.Dump(result) - g.Dump(err) - - // Output - // hello gf 2021! - // null -} - -func ExampleReplaceStringFunc() { - patternStr := `[1-9]\d*` - str := "hello gf 2018~2020!" - - // 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(patternStr, str, func(b string) string { - - g.Dump(b) - - replaceStr := "2021" - if b == "2020" { + if replaceStr, ok := replaceStrMap[string(b)]; ok { return replaceStr } return b @@ -239,46 +166,116 @@ func ExampleReplaceStringFunc() { g.Dump(err) // Output - // 2018 - // 2020 - // hello gf 2018~2021! - // null + // "2018" + // "2020" + // "hello gf 2018~2021!" + // } -func ExampleReplaceStringFuncMatch() { - patternStr := `[1-9]\d*` - str := "hello gf 2018~2020!" - - // 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.ReplaceStringFuncMatch(patternStr, str, func(b []string) string { - - g.Dump(b) - - replaceStr := "2021" - for _, v := range b { - if v == "2020" { +func ExampleReplaceFuncMatch() { + var ( + patternStr = `[1-9]\d+` + str = "hello gf 2018~2020!" + replaceMap = map[string][]byte{ + "2020": []byte("2021"), + } + ) + // 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) + for _, v := range match { + replaceStr, ok := replaceMap[string(v)] + if ok { return replaceStr } } - return b[0] + return match[0] }) - g.Dump(result) g.Dump(err) // Output // ["2018"] // ["2020"] - // hello gf 2018~2021! - // null + // "hello gf 2018~2021!" + // +} + +func ExampleReplaceString() { + patternStr := `[1-9]\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() { + var ( + patternStr = `[1-9]\d+` + str = "hello gf 2018~2020!" + 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(patternStr, str, func(b string) string { + g.Dump(b) + if replaceStr, ok := replaceStrMap[b]; ok { + return replaceStr + } + return b + }) + g.Dump(result) + g.Dump(err) + + // Output + // "2018" + // "2020" + // "hello gf 2018~2021!" + // +} + +func ExampleReplaceStringFuncMatch() { + var ( + patternStr = `[1-9]\d+` + str = "hello gf 2018~2020!" + 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.ReplaceStringFuncMatch(patternStr, str, func(b []string) string { + g.Dump(b) + for _, v := range b { + if replaceStr, ok := replaceStrMap[v]; ok { + return replaceStr + } + } + return b[0] + }) + g.Dump(result) + g.Dump(err) + + // Output + // ["2018"] + // ["2020"] + // "hello gf 2018~2021!" + // } func ExampleSplit() { - patternStr := `[1-9]\d*` + patternStr := `[1-9]\d+` str := "hello2020gf" result := gregex.Split(patternStr, str) - g.Dump(result) // Output @@ -287,12 +284,12 @@ func ExampleSplit() { func ExampleValidate() { // Valid match statement - g.Dump(gregex.Validate(`[1-9]\d*`)) + g.Dump(gregex.Validate(`[1-9]\d+`)) // Mismatched statement - g.Dump(gregex.Validate(`[a-9]\d*`)) + g.Dump(gregex.Validate(`[a-9]\d+`)) // Output - // null + // // { // "Code": "invalid character class range", // "Expr": "a-9" From 5776b2596dbe04c464c4835bb63617433015b7dc Mon Sep 17 00:00:00 2001 From: visualsun Date: Thu, 4 Nov 2021 22:17:32 +0800 Subject: [PATCH 07/22] Create garray_z_example_sorted_str_test.go --- .../garray_z_example_sorted_str_test.go | 568 ++++++++++++++++++ 1 file changed, 568 insertions(+) create mode 100644 container/garray/garray_z_example_sorted_str_test.go 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..b3824bf07 --- /dev/null +++ b/container/garray/garray_z_example_sorted_str_test.go @@ -0,0 +1,568 @@ +// 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 ExampleSortedStrArray_NewSortedStrArray() { + 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 ExampleSortedStrArray_NewSortedStrArraySize() { + 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 ExampleSortedStrArray_NewStrArrayFromCopy() { + 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.Unique()) + + // Output: + // ["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 + 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 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.FilterEmpty()) + + // Output: + // ["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 +} From 613958a4b6b5b7eb2f4d7749ac69462890afe2c2 Mon Sep 17 00:00:00 2001 From: "timmy.hu" Date: Fri, 5 Nov 2021 00:50:44 +0800 Subject: [PATCH 08/22] IntSet finish --- container/gset/gset_z_example_int_test.go | 392 +++++++++++++++++++++- 1 file changed, 388 insertions(+), 4 deletions(-) diff --git a/container/gset/gset_z_example_int_test.go b/container/gset/gset_z_example_int_test.go index 761e3552f..b3a270127 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(true) + 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}, true) + 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}, true) + 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}, true) + 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}, true) + 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}, true) + 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}, true) + 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}, true) + s := gset.NewIntSetFrom([]int{1, 2, 3}, true) + 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}, true) + s2 := gset.NewIntSetFrom([]int{1, 2, 3, 4}, true) + 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}, true) + s2 := gset.NewIntSetFrom([]int{1, 2, 3, 4}, true) + fmt.Println(s2.Equal(s1)) + + s3 := gset.NewIntSetFrom([]int{1, 2, 3}, true) + s4 := gset.NewIntSetFrom([]int{1, 2, 3}, 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 ExampleIntSet_Intersect() { + s1 := gset.NewIntSet(true) + 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(true) + 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(true) + 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(true) + 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(true) + 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}, 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 ExampleIntSet_Merge() { + s1 := gset.NewIntSet(true) + s1.Add([]int{1, 2, 3, 4}...) + + s2 := gset.NewIntSet(true) + 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(true) + 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(true) + 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(true) + 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(true) + s1.Add([]int{1, 2, 3, 4}...) + s1.Remove(1) + fmt.Println(s1.Slice()) + + // Output: + // [3 4 2] +} + +// Size returns the size of the set. +func ExampleIntSet_Size() { + s1 := gset.NewIntSet(true) + 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(true) + 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(true) + 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(true) + 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(true) + s1.Add([]int{1, 2, 3, 4}...) + s2 := gset.NewIntSet(true) + 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} + prefix = 10 + ) + set.Add(names...) + // Add prefix for given table names. + set.Walk(func(item int) int { + return prefix + item + }) + fmt.Println(set.Slice()) + + // May Output: + // [12 60] +} From ea7d963f204ceb5da505ba3daad3527ad9847fc1 Mon Sep 17 00:00:00 2001 From: "timmy.hu" Date: Fri, 5 Nov 2021 00:56:59 +0800 Subject: [PATCH 09/22] IntSet --- container/gset/gset_z_example_int_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/gset/gset_z_example_int_test.go b/container/gset/gset_z_example_int_test.go index b3a270127..dfc832fe3 100644 --- a/container/gset/gset_z_example_int_test.go +++ b/container/gset/gset_z_example_int_test.go @@ -298,7 +298,7 @@ func ExampleIntSet_Remove() { s1.Remove(1) fmt.Println(s1.Slice()) - // Output: + // May Output: // [3 4 2] } From 4acc0e987660a43cedc2ac8413c4a7c1b1086890 Mon Sep 17 00:00:00 2001 From: John Guo Date: Fri, 5 Nov 2021 01:15:11 +0800 Subject: [PATCH 10/22] gconv.ScanList --- util/gconv/gconv_scan.go | 402 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+) diff --git a/util/gconv/gconv_scan.go b/util/gconv/gconv_scan.go index 8df73d0e7..76ebcb149 100644 --- a/util/gconv/gconv_scan.go +++ b/util/gconv/gconv_scan.go @@ -7,8 +7,12 @@ package gconv 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/gutil" "reflect" ) @@ -94,3 +98,401 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) return doStruct(params, pointer, keyToAttributeNameMapping, "") } } + +// ScanList converts `data` to struct slice which contains other complex struct attributes. +// 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 +// UserDetail *EntityUserDetail +// UserScores []*EntityUserScores +// } +// 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") +func ScanList(data interface{}, 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(data, structSlicePointer, bindToAttrName, relationAttrName, relationFields) +} + +// doScanList converts `data` to struct slice which contains other complex struct attributes recursively. +// 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(data interface{}, structSlicePointer interface{}, bindToAttrName, relationAttrName, relationFields string) (err error) { + if data == nil { + return nil + } + // Necessary checks for parameters. + if bindToAttrName == "" { + return gerror.NewCode(gcode.CodeInvalidParameter, `bindToAttrName should not be empty`) + } + + if relationAttrName == "." { + relationAttrName = "" + } + + var ( + reflectValue = reflect.ValueOf(structSlicePointer) + reflectKind = reflectValue.Kind() + ) + if reflectKind == reflect.Interface { + reflectValue = reflectValue.Elem() + reflectKind = reflectValue.Kind() + } + if reflectKind != reflect.Ptr { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + "structSlicePointer should be type of *[]struct/*[]*struct, but got: %v", + reflectKind, + ) + } + reflectValue = reflectValue.Elem() + reflectKind = reflectValue.Kind() + if reflectKind != reflect.Slice && reflectKind != reflect.Array { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + "structSlicePointer should be type of *[]struct/*[]*struct, but got: %v", + reflectKind, + ) + } + var ( + arrayValue reflect.Value // Like: []*Entity + arrayItemType reflect.Type // Like: *Entity + reflectType = reflect.TypeOf(structSlicePointer) + ) + if reflectValue.Len() > 0 { + arrayValue = reflectValue + } else { + arrayValue = reflect.MakeSlice(reflectType.Elem(), length, length) + } + + // Slice element item. + arrayItemType = arrayValue.Index(0).Type() + + // Relation variables. + var ( + relationDataMap map[string]Value + relationFromFieldName string // Eg: relationKV: id:uid -> id + relationBindToFieldName string // Eg: relationKV: id:uid -> uid + ) + if len(relationFields) > 0 { + // The relation key string of table filed name and attribute name + // can be joined with char '=' or ':'. + array := gstr.SplitAndTrim(relationFields, "=") + if len(array) == 1 { + // Compatible with old splitting char ':'. + array = gstr.SplitAndTrim(relationFields, ":") + } + if len(array) == 1 { + // The relation names are the same. + array = []string{relationFields, relationFields} + } + if len(array) == 2 { + // Defined table field to relation attribute name. + // Like: + // uid:Uid + // uid:UserId + 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 fields "%s"`, + relationFromFieldName, + relationFields, + ) + } else { + relationFromFieldName = key + } + } else { + return gerror.NewCode( + gcode.CodeInvalidParameter, + `parameter relationKV should be format of "ResultFieldName:BindToAttrName"`, + ) + } + if relationFromFieldName != "" { + // Note that the value might be type of slice. + relationDataMap = result.MapKeyValue(relationFromFieldName) + } + if len(relationDataMap) == 0 { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + `cannot find the relation data map, maybe invalid relation fields given "%v"`, + relationFields, + ) + } + } + // Bind to target attribute. + var ( + ok bool + bindToAttrValue reflect.Value + bindToAttrKind reflect.Kind + bindToAttrType reflect.Type + bindToAttrField reflect.StructField + ) + if arrayItemType.Kind() == reflect.Ptr { + if bindToAttrField, ok = arrayItemType.Elem().FieldByName(bindToAttrName); !ok { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + `invalid parameter bindToAttrName: cannot find attribute with name "%s" from slice element`, + bindToAttrName, + ) + } + } else { + if bindToAttrField, ok = arrayItemType.FieldByName(bindToAttrName); !ok { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + `invalid parameter bindToAttrName: cannot find attribute with name "%s" from slice element`, + bindToAttrName, + ) + } + } + bindToAttrType = bindToAttrField.Type + bindToAttrKind = bindToAttrType.Kind() + + // Bind to relation conditions. + var ( + relationFromAttrValue reflect.Value + relationFromAttrField reflect.Value + relationBindToFieldNameChecked bool + ) + for i := 0; i < arrayValue.Len(); i++ { + arrayElemValue := arrayValue.Index(i) + // The FieldByName should be called on non-pointer reflect.Value. + if arrayElemValue.Kind() == reflect.Ptr { + // Like: []*Entity + arrayElemValue = arrayElemValue.Elem() + if !arrayElemValue.IsValid() { + // The element is nil, then create one and set it to the slice. + // The "reflect.New(itemType.Elem())" creates a new element and returns the address of it. + // For example: + // reflect.New(itemType.Elem()) => *Entity + // reflect.New(itemType.Elem()).Elem() => Entity + arrayElemValue = reflect.New(arrayItemType.Elem()).Elem() + arrayValue.Index(i).Set(arrayElemValue.Addr()) + } + } else { + // Like: []Entity + } + bindToAttrValue = arrayElemValue.FieldByName(bindToAttrName) + if relationAttrName != "" { + // Attribute value of current slice element. + relationFromAttrValue = arrayElemValue.FieldByName(relationAttrName) + if relationFromAttrValue.Kind() == reflect.Ptr { + relationFromAttrValue = relationFromAttrValue.Elem() + } + } else { + // Current slice element. + relationFromAttrValue = arrayElemValue + } + if len(relationDataMap) > 0 && !relationFromAttrValue.IsValid() { + return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) + } + // Check and find possible bind to attribute name. + if relationFields != "" && !relationBindToFieldNameChecked { + relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) + if !relationFromAttrField.IsValid() { + var ( + filedMap, _ = structs.FieldMap(structs.FieldMapInput{ + Pointer: relationFromAttrValue, + RecursiveOption: structs.RecursiveOptionEmbeddedNoTag, + }) + ) + if key, _ := gutil.MapPossibleItemByKey(gconv.Map(filedMap), relationBindToFieldName); key == "" { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + `cannot find possible related attribute name "%s" from given relation fields "%s"`, + relationBindToFieldName, + relationFields, + ) + } else { + relationBindToFieldName = key + } + } + relationBindToFieldNameChecked = true + } + switch bindToAttrKind { + case reflect.Array, reflect.Slice: + if len(relationDataMap) > 0 { + relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) + if relationFromAttrField.IsValid() { + results := make(Result, 0) + for _, v := range relationDataMap[gconv.String(relationFromAttrField.Interface())].Slice() { + results = append(results, v.(Record)) + } + if err = results.Structs(bindToAttrValue.Addr()); err != nil { + return err + } + // Recursively Scan. + if model != nil { + if err = model.doWithScanStructs(bindToAttrValue.Addr()); err != nil { + return nil + } + } + } else { + // Maybe the attribute does not exist yet. + return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) + } + } else { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + `relationKey should not be empty as field "%s" is slice`, + bindToAttrName, + ) + } + + case reflect.Ptr: + var element reflect.Value + if bindToAttrValue.IsNil() { + element = reflect.New(bindToAttrType.Elem()).Elem() + } else { + element = bindToAttrValue.Elem() + } + if len(relationDataMap) > 0 { + relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) + if relationFromAttrField.IsValid() { + v := relationDataMap[gconv.String(relationFromAttrField.Interface())] + if v == nil { + // There's no relational data. + continue + } + if v.IsSlice() { + if err = v.Slice()[0].(Record).Struct(element); err != nil { + return err + } + } else { + if err = v.Val().(Record).Struct(element); err != nil { + return err + } + } + } else { + // Maybe the attribute does not exist yet. + return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) + } + } else { + if i >= len(result) { + // There's no relational data. + continue + } + v := result[i] + if v == nil { + // There's no relational data. + continue + } + if err = v.Struct(element); err != nil { + return err + } + } + // Recursively Scan. + if model != nil { + if err = model.doWithScanStruct(element); err != nil { + return err + } + } + bindToAttrValue.Set(element.Addr()) + + case reflect.Struct: + if len(relationDataMap) > 0 { + relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) + if relationFromAttrField.IsValid() { + relationDataItem := relationDataMap[gconv.String(relationFromAttrField.Interface())] + if relationDataItem == nil { + // There's no relational data. + continue + } + if relationDataItem.IsSlice() { + if err = relationDataItem.Slice()[0].(Record).Struct(bindToAttrValue); err != nil { + return err + } + } else { + if err = relationDataItem.Val().(Record).Struct(bindToAttrValue); err != nil { + return err + } + } + } else { + // Maybe the attribute does not exist yet. + return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) + } + } else { + if i >= len(result) { + // There's no relational data. + continue + } + relationDataItem := result[i] + if relationDataItem == nil { + // There's no relational data. + continue + } + if err = relationDataItem.Struct(bindToAttrValue); err != nil { + return err + } + } + // Recursively Scan. + if model != nil { + if err = model.doWithScanStruct(bindToAttrValue); err != nil { + return err + } + } + + default: + return gerror.NewCodef(gcode.CodeInvalidParameter, `unsupported attribute type: %s`, bindToAttrKind.String()) + } + } + reflect.ValueOf(structSlicePointer).Elem().Set(arrayValue) + return nil +} From 12514a0311bf8eee1dd53adb747b3efdfc95e997 Mon Sep 17 00:00:00 2001 From: visualsun Date: Fri, 5 Nov 2021 14:45:04 +0800 Subject: [PATCH 11/22] Update garray_z_example_sorted_str_test.go --- .../garray_z_example_sorted_str_test.go | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/container/garray/garray_z_example_sorted_str_test.go b/container/garray/garray_z_example_sorted_str_test.go index b3824bf07..7fdce61b9 100644 --- a/container/garray/garray_z_example_sorted_str_test.go +++ b/container/garray/garray_z_example_sorted_str_test.go @@ -29,7 +29,7 @@ func ExampleSortedStrArray_Walk() { // [gf_user gf_user_detail] } -func ExampleSortedStrArray_NewSortedStrArray() { +func ExampleNewSortedStrArray() { s := garray.NewSortedStrArray() s.Append("b") s.Append("d") @@ -41,7 +41,7 @@ func ExampleSortedStrArray_NewSortedStrArray() { // [a b c d] } -func ExampleSortedStrArray_NewSortedStrArraySize() { +func ExampleNewSortedStrArraySize() { s := garray.NewSortedStrArraySize(3) s.SetArray([]string{"b", "d", "a", "c"}) fmt.Println(s.Slice(), s.Len(), cap(s.Slice())) @@ -50,7 +50,7 @@ func ExampleSortedStrArray_NewSortedStrArraySize() { // [a b c d] 4 4 } -func ExampleSortedStrArray_NewStrArrayFromCopy() { +func ExampleNewStrArrayFromCopy() { s := garray.NewSortedStrArrayFromCopy(g.SliceStr{"b", "d", "c", "a"}) fmt.Println(s.Slice()) @@ -363,9 +363,11 @@ func ExampleSortedStrArray_Search() { 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"] } @@ -493,20 +495,21 @@ func ExampleSortedStrArray_String() { func ExampleSortedStrArray_MarshalJSON() { type Student struct { - ID int - Name string - Lessons []string + ID int + Name string + Levels garray.SortedStrArray } + r := garray.NewSortedStrArrayFrom(g.SliceStr{"b", "c", "a"}) s := Student{ - ID: 1, - Name: "john", - Lessons: []string{"Math", "English", "Music"}, + ID: 1, + Name: "john", + Levels: *r, } b, _ := json.Marshal(s) fmt.Println(string(b)) // Output: - // {"ID":1,"Name":"john","Lessons":["Math","English","Music"]} + // {"ID":1,"Name":"john","Level":["a","b","c"]} } func ExampleSortedStrArray_UnmarshalJSON() { @@ -550,9 +553,11 @@ func ExampleSortedStrArray_UnmarshalValue() { 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"] } From 2511c378f260386252e7a821cb63630c80e47603 Mon Sep 17 00:00:00 2001 From: visualsun Date: Fri, 5 Nov 2021 17:02:28 +0800 Subject: [PATCH 12/22] Create garray_z_example_int_test.go --- container/garray/garray_z_example_int_test.go | 709 ++++++++++++++++++ 1 file changed, 709 insertions(+) create mode 100644 container/garray/garray_z_example_int_test.go 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 +} From e7b63839c83749d16f31b5932e96cc51f5600ab8 Mon Sep 17 00:00:00 2001 From: visualsun Date: Fri, 5 Nov 2021 19:31:11 +0800 Subject: [PATCH 13/22] Update garray_z_example_sorted_str_test.go --- container/garray/garray_z_example_sorted_str_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/garray/garray_z_example_sorted_str_test.go b/container/garray/garray_z_example_sorted_str_test.go index 7fdce61b9..0c9c83a51 100644 --- a/container/garray/garray_z_example_sorted_str_test.go +++ b/container/garray/garray_z_example_sorted_str_test.go @@ -509,7 +509,7 @@ func ExampleSortedStrArray_MarshalJSON() { fmt.Println(string(b)) // Output: - // {"ID":1,"Name":"john","Level":["a","b","c"]} + // {"ID":1,"Name":"john","Levels":["a","b","c"]} } func ExampleSortedStrArray_UnmarshalJSON() { From 24f759e00ea8017eaf0b94690e8c66a2389c8602 Mon Sep 17 00:00:00 2001 From: daguang Date: Fri, 5 Nov 2021 23:56:08 +0800 Subject: [PATCH 14/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 208 ++++++++++----------------- 1 file changed, 75 insertions(+), 133 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index d4196470d..af8612322 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -6,8 +6,10 @@ package gregex_test import ( + "bytes" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/text/gregex" + "strings" ) func ExampleIsMatch() { @@ -35,92 +37,57 @@ func ExampleIsMatchString() { } func ExampleMatch() { - patternStr := `[1-9]\d+` - result, err := gregex.Match(patternStr, []byte("hello 2022! hello gf!")) - g.Dump(result) - g.Dump(err) - - result, err = gregex.Match(patternStr, nil) - g.Dump(result) - g.Dump(err) - - result, err = gregex.Match(patternStr, []byte("hello easy gf!")) + 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 - // ["2022"] - // - // [] - // - // [] - // -} - -func ExampleMatchAll() { - patternStr := `[1-9]\d+` - results, err := gregex.MatchAll(patternStr, []byte("goodBye 2021! hello 2022! hello gf!")) - g.Dump(results) - g.Dump(err) - - results, err = gregex.MatchAll(patternStr, []byte("hello gf!")) - g.Dump(results) - g.Dump(err) - - results, err = gregex.MatchAll(patternStr, nil) - g.Dump(results) - g.Dump(err) - - // Output - // [["2021"],["2022"]] - // - // [] - // - // [] - // -} - -func ExampleMatchAllString() { - patternStr := `[1-9]\d+` - results, err := gregex.MatchAllString(patternStr, "goodBye 2021! hello 2022! hello gf!") - g.Dump(results) - g.Dump(err) - - results, err = gregex.MatchAllString(patternStr, "hello gf!") - g.Dump(results) - g.Dump(err) - - results, err = gregex.MatchAllString(patternStr, "") - g.Dump(results) - g.Dump(err) - - // Output - // [["2021"],["2022"]] - // - // [] - // - // [] + // ["pageId=1114219","pageId","1114219"] // } func ExampleMatchString() { - var str = "goodBye 2021! hello 2022! hello gf!" - patternStr := `[1-9]\d+` - // if you need a greed match, should use <..all> methods - results, err := gregex.MatchString(patternStr, str) - - g.Dump(results) + 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 - // ["2021"] + // ["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() { - patternStr := `[1-9]\d+` - result := gregex.Quote(patternStr) - + result := gregex.Quote(`[1-9]\d+`) g.Dump(result) // Output @@ -134,7 +101,6 @@ func ExampleReplace() { repStr = "2021" result, err = gregex.Replace(patternStr, []byte(repStr), []byte(str)) ) - g.Dump(err) g.Dump(result) @@ -144,61 +110,43 @@ func ExampleReplace() { } func ExampleReplaceFunc() { - var ( - patternStr = `[1-9]\d+` - str = "hello gf 2018~2020!" - replaceStrMap = map[string][]byte{ - "2020": []byte("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.ReplaceFunc(patternStr, []byte(str), func(b []byte) []byte { - g.Dump(b) - if replaceStr, ok := replaceStrMap[string(b)]; ok { - return replaceStr - } - return b + // 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" + // Output: + // [ + // "2018~2020", + // "2018", + // "2020", + // ] // "hello gf 2018~2021!" - // } func ExampleReplaceFuncMatch() { var ( - patternStr = `[1-9]\d+` + patternStr = `(\d+)~(\d+)` str = "hello gf 2018~2020!" - replaceMap = map[string][]byte{ - "2020": []byte("2021"), - } ) // 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) - for _, v := range match { - replaceStr, ok := replaceMap[string(v)] - if ok { - return replaceStr - } - } - return match[0] + match[2] = []byte("2021") + return bytes.Join(match[1:], []byte("-")) }) g.Dump(result) g.Dump(err) // Output - // ["2018"] - // ["2020"] - // "hello gf 2018~2021!" + // ["2018~2020","2018","2020"] + // "hello gf 2018-2021!" // } @@ -217,16 +165,12 @@ func ExampleReplaceString() { } func ExampleReplaceStringFunc() { - var ( - patternStr = `[1-9]\d+` - str = "hello gf 2018~2020!" - replaceStrMap = map[string]string{ - "2020": "2021", - } - ) + 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(patternStr, str, func(b string) string { + result, err := gregex.ReplaceStringFunc(`[1-9]\d+`, `hello gf 2018~2020!`, func(b string) string { g.Dump(b) if replaceStr, ok := replaceStrMap[b]; ok { return replaceStr @@ -236,39 +180,37 @@ func ExampleReplaceStringFunc() { 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 = `[1-9]\d+` - str = "hello gf 2018~2020!" - replaceStrMap = map[string]string{ - "2020": "2021", - } + patternStr = `([A-Z])\w+` + str = "hello Golang 2018~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.ReplaceStringFuncMatch(patternStr, str, func(b []string) string { - g.Dump(b) - for _, v := range b { - if replaceStr, ok := replaceStrMap[v]; ok { - return replaceStr - } - } - return b[0] + // 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 - // ["2018"] - // ["2020"] - // "hello gf 2018~2021!" + // ["Golang","G"] + // "hello Gf 2018~2021!" // } From 99d2186c8cfa4156bd5d4ba955eb0fcc2309da9f Mon Sep 17 00:00:00 2001 From: daguang Date: Sat, 6 Nov 2021 00:06:56 +0800 Subject: [PATCH 15/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index af8612322..99828f988 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -127,6 +127,7 @@ func ExampleReplaceFunc() { // "2020", // ] // "hello gf 2018~2021!" + // } func ExampleReplaceFuncMatch() { From 64fa8d52828ce0e6ae9b3872e97907fe8dc5343b Mon Sep 17 00:00:00 2001 From: daguang Date: Sat, 6 Nov 2021 00:49:15 +0800 Subject: [PATCH 16/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index 99828f988..7c4a7857e 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -13,7 +13,7 @@ import ( ) func ExampleIsMatch() { - patternStr := `[1-9]\d+` + 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!"))) @@ -25,7 +25,7 @@ func ExampleIsMatch() { } func ExampleIsMatchString() { - patternStr := `[1-9]\d+` + patternStr := `\d+` g.Dump(gregex.IsMatchString(patternStr, "hello 2022! hello gf!")) g.Dump(gregex.IsMatchString(patternStr, "hello gf!")) g.Dump(gregex.IsMatchString(patternStr, "")) @@ -96,7 +96,7 @@ func ExampleQuote() { func ExampleReplace() { var ( - patternStr = `[1-9]\d+` + patternStr = `\d+` str = "hello gf 2020!" repStr = "2021" result, err = gregex.Replace(patternStr, []byte(repStr), []byte(str)) @@ -152,7 +152,7 @@ func ExampleReplaceFuncMatch() { } func ExampleReplaceString() { - patternStr := `[1-9]\d+` + patternStr := `\d+` str := "hello gf 2020!" replaceStr := "2021" result, err := gregex.ReplaceString(patternStr, replaceStr, str) @@ -171,7 +171,7 @@ func ExampleReplaceStringFunc() { } // 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(`[1-9]\d+`, `hello gf 2018~2020!`, func(b string) string { + result, err := gregex.ReplaceStringFunc(`\d+`, `hello gf 2018~2020!`, func(b string) string { g.Dump(b) if replaceStr, ok := replaceStrMap[b]; ok { return replaceStr @@ -216,7 +216,7 @@ func ExampleReplaceStringFuncMatch() { } func ExampleSplit() { - patternStr := `[1-9]\d+` + patternStr := `\d+` str := "hello2020gf" result := gregex.Split(patternStr, str) g.Dump(result) @@ -227,7 +227,7 @@ func ExampleSplit() { func ExampleValidate() { // Valid match statement - g.Dump(gregex.Validate(`[1-9]\d+`)) + g.Dump(gregex.Validate(`\d+`)) // Mismatched statement g.Dump(gregex.Validate(`[a-9]\d+`)) From 1a596fe84d7996f6bccdc32965d09a02761c55b2 Mon Sep 17 00:00:00 2001 From: daguang Date: Sat, 6 Nov 2021 00:54:10 +0800 Subject: [PATCH 17/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index 7c4a7857e..8acf97325 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -18,7 +18,7 @@ func ExampleIsMatch() { g.Dump(gregex.IsMatch(patternStr, nil)) g.Dump(gregex.IsMatch(patternStr, []byte("hello gf!"))) - // Output + // Output: // true // false // false @@ -30,7 +30,7 @@ func ExampleIsMatchString() { g.Dump(gregex.IsMatchString(patternStr, "hello gf!")) g.Dump(gregex.IsMatchString(patternStr, "")) - // Output + // Output: // true // false // false @@ -44,7 +44,7 @@ func ExampleMatch() { g.Dump(result) g.Dump(err) - // Output + // Output: // ["pageId=1114219","pageId","1114219"] // } @@ -57,7 +57,7 @@ func ExampleMatchString() { g.Dump(result) g.Dump(err) - // Output + // Output: // ["pageId=1114219","pageId","1114219"] // } @@ -69,7 +69,7 @@ func ExampleMatchAll() { g.Dump(result) g.Dump(err) - // Output + // Output: // [["pageId=1114219","pageId","1114219",],["searchId=8QC5D1D2E","searchId","8QC5D1D2E"]] // } @@ -81,7 +81,7 @@ func ExampleMatchAllString() { g.Dump(result) g.Dump(err) - // Output + // Output: // [["pageId=1114219","pageId","1114219",],["searchId=8QC5D1D2E","searchId","8QC5D1D2E"]] // } @@ -90,7 +90,7 @@ func ExampleQuote() { result := gregex.Quote(`[1-9]\d+`) g.Dump(result) - // Output + // Output: // "\[1-9\]\\d\+" } @@ -104,7 +104,7 @@ func ExampleReplace() { g.Dump(err) g.Dump(result) - // Output + // Output: // // "hello gf 2021!" } @@ -120,7 +120,7 @@ func ExampleReplaceFunc() { g.Dump(result) g.Dump(err) - // Output: + // Output:: // [ // "2018~2020", // "2018", @@ -145,7 +145,7 @@ func ExampleReplaceFuncMatch() { g.Dump(result) g.Dump(err) - // Output + // Output: // ["2018~2020","2018","2020"] // "hello gf 2018-2021!" // @@ -160,7 +160,7 @@ func ExampleReplaceString() { g.Dump(result) g.Dump(err) - // Output + // Output: // "hello gf 2021!" // } @@ -185,7 +185,7 @@ func ExampleReplaceStringFunc() { g.Dump(result) g.Dump(err) - // Output + // Output: // "2018" // "2020" // "hello gf 2018~2021!" @@ -209,7 +209,7 @@ func ExampleReplaceStringFuncMatch() { g.Dump(result) g.Dump(err) - // Output + // Output: // ["Golang","G"] // "hello Gf 2018~2021!" // @@ -221,7 +221,7 @@ func ExampleSplit() { result := gregex.Split(patternStr, str) g.Dump(result) - // Output + // Output: // ["hello","gf"] } @@ -231,7 +231,7 @@ func ExampleValidate() { // Mismatched statement g.Dump(gregex.Validate(`[a-9]\d+`)) - // Output + // Output: // // { // "Code": "invalid character class range", From b967cf62247c881a07d26a00a555a799f453cef8 Mon Sep 17 00:00:00 2001 From: daguang Date: Sat, 6 Nov 2021 01:16:51 +0800 Subject: [PATCH 18/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 66 ++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 13 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index 8acf97325..5c0c55f4a 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -45,7 +45,11 @@ func ExampleMatch() { g.Dump(err) // Output: - // ["pageId=1114219","pageId","1114219"] + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ] // } @@ -58,7 +62,11 @@ func ExampleMatchString() { g.Dump(err) // Output: - // ["pageId=1114219","pageId","1114219"] + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ] // } @@ -70,7 +78,18 @@ func ExampleMatchAll() { g.Dump(err) // Output: - // [["pageId=1114219","pageId","1114219",],["searchId=8QC5D1D2E","searchId","8QC5D1D2E"]] + // [ + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ], + // [ + // "searchId=8QC5D1D2E", + // "searchId", + // "8QC5D1D2E", + // ], + // ] // } @@ -82,7 +101,18 @@ func ExampleMatchAllString() { g.Dump(err) // Output: - // [["pageId=1114219","pageId","1114219",],["searchId=8QC5D1D2E","searchId","8QC5D1D2E"]] + // [ + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ], + // [ + // "searchId=8QC5D1D2E", + // "searchId", + // "8QC5D1D2E", + // ], + // ] // } @@ -120,11 +150,11 @@ func ExampleReplaceFunc() { g.Dump(result) g.Dump(err) - // Output:: + // Output: // [ - // "2018~2020", - // "2018", - // "2020", + // "2018~2020", + // "2018", + // "2020", // ] // "hello gf 2018~2021!" // @@ -146,7 +176,11 @@ func ExampleReplaceFuncMatch() { g.Dump(err) // Output: - // ["2018~2020","2018","2020"] + // [ + // "2018~2020", + // "2018", + // "2020", + // ] // "hello gf 2018-2021!" // } @@ -210,7 +244,10 @@ func ExampleReplaceStringFuncMatch() { g.Dump(err) // Output: - // ["Golang","G"] + // [ + // "Golang", + // "G", + // ] // "hello Gf 2018~2021!" // } @@ -222,7 +259,10 @@ func ExampleSplit() { g.Dump(result) // Output: - // ["hello","gf"] + // [ + // "hello", + // "gf", + // ] } func ExampleValidate() { @@ -234,7 +274,7 @@ func ExampleValidate() { // Output: // // { - // "Code": "invalid character class range", - // "Expr": "a-9" + // Code: "invalid character class range", + // Expr: "a-9", // } } From b036767fc083b21c544bcbc2a49450a7450575b6 Mon Sep 17 00:00:00 2001 From: daguang Date: Sat, 6 Nov 2021 01:47:00 +0800 Subject: [PATCH 19/22] :memo: add example --- text/gregex/gregex_z_example_test.go | 78 ++++++++++++++-------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/text/gregex/gregex_z_example_test.go b/text/gregex/gregex_z_example_test.go index 5c0c55f4a..ecf6128d7 100644 --- a/text/gregex/gregex_z_example_test.go +++ b/text/gregex/gregex_z_example_test.go @@ -46,9 +46,9 @@ func ExampleMatch() { // Output: // [ - // "pageId=1114219", - // "pageId", - // "1114219", + // "pageId=1114219", + // "pageId", + // "1114219", // ] // } @@ -63,9 +63,9 @@ func ExampleMatchString() { // Output: // [ - // "pageId=1114219", - // "pageId", - // "1114219", + // "pageId=1114219", + // "pageId", + // "1114219", // ] // } @@ -78,17 +78,17 @@ func ExampleMatchAll() { g.Dump(err) // Output: - // [ - // [ - // "pageId=1114219", - // "pageId", - // "1114219", - // ], - // [ - // "searchId=8QC5D1D2E", - // "searchId", - // "8QC5D1D2E", - // ], + // [ + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ], + // [ + // "searchId=8QC5D1D2E", + // "searchId", + // "8QC5D1D2E", + // ], // ] // } @@ -102,16 +102,16 @@ func ExampleMatchAllString() { // Output: // [ - // [ - // "pageId=1114219", - // "pageId", - // "1114219", - // ], - // [ - // "searchId=8QC5D1D2E", - // "searchId", - // "8QC5D1D2E", - // ], + // [ + // "pageId=1114219", + // "pageId", + // "1114219", + // ], + // [ + // "searchId=8QC5D1D2E", + // "searchId", + // "8QC5D1D2E", + // ], // ] // } @@ -152,9 +152,9 @@ func ExampleReplaceFunc() { // Output: // [ - // "2018~2020", - // "2018", - // "2020", + // "2018~2020", + // "2018", + // "2020", // ] // "hello gf 2018~2021!" // @@ -177,9 +177,9 @@ func ExampleReplaceFuncMatch() { // Output: // [ - // "2018~2020", - // "2018", - // "2020", + // "2018~2020", + // "2018", + // "2020", // ] // "hello gf 2018-2021!" // @@ -245,8 +245,8 @@ func ExampleReplaceStringFuncMatch() { // Output: // [ - // "Golang", - // "G", + // "Golang", + // "G", // ] // "hello Gf 2018~2021!" // @@ -260,8 +260,8 @@ func ExampleSplit() { // Output: // [ - // "hello", - // "gf", + // "hello", + // "gf", // ] } @@ -274,7 +274,7 @@ func ExampleValidate() { // Output: // // { - // Code: "invalid character class range", - // Expr: "a-9", + // Code: "invalid character class range", + // Expr: "a-9", // } } From 15f9b69b36b056a33d7a570573bb9ffeb91a1c5e Mon Sep 17 00:00:00 2001 From: "timmy.hu" Date: Sat, 6 Nov 2021 06:38:28 +0800 Subject: [PATCH 20/22] fix --- container/gset/gset_z_example_int_test.go | 74 +++++++++++------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/container/gset/gset_z_example_int_test.go b/container/gset/gset_z_example_int_test.go index dfc832fe3..d5d2cb411 100644 --- a/container/gset/gset_z_example_int_test.go +++ b/container/gset/gset_z_example_int_test.go @@ -17,7 +17,7 @@ import ( // The parameter `safe` is used to specify whether using set in concurrent-safety, // which is false in default. func ExampleNewIntSet() { - intSet := gset.NewIntSet(true) + intSet := gset.NewIntSet() intSet.Add([]int{1, 2, 3}...) fmt.Println(intSet.Slice()) @@ -27,7 +27,7 @@ func ExampleNewIntSet() { // NewIntSetFrom returns a new set from `items`. func ExampleNewFrom() { - intSet := gset.NewIntSetFrom([]int{1, 2, 3}, true) + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) fmt.Println(intSet.Slice()) // May Output: @@ -36,7 +36,7 @@ func ExampleNewFrom() { // Add adds one or multiple items to the set. func ExampleIntSet_Add() { - intSet := gset.NewIntSetFrom([]int{1, 2, 3}, true) + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) intSet.Add(1) fmt.Println(intSet.Slice()) fmt.Println(intSet.AddIfNotExist(1)) @@ -50,7 +50,7 @@ func ExampleIntSet_Add() { // 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}, true) + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) intSet.Add(1) fmt.Println(intSet.Slice()) fmt.Println(intSet.AddIfNotExist(1)) @@ -65,7 +65,7 @@ func ExampleIntSet_AddIfNotExist() { // 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}, true) + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) intSet.Add(1) fmt.Println(intSet.Slice()) fmt.Println(intSet.AddIfNotExistFunc(5, func() bool { @@ -82,7 +82,7 @@ func ExampleIntSet_AddIfNotExistFunc() { // 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}, true) + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) intSet.Add(1) fmt.Println(intSet.Slice()) fmt.Println(intSet.AddIfNotExistFuncLock(4, func() bool { @@ -96,7 +96,7 @@ func ExampleIntSet_AddIfNotExistFuncLock() { // Clear deletes all items of the set. func ExampleIntSet_Clear() { - intSet := gset.NewIntSetFrom([]int{1, 2, 3}, true) + intSet := gset.NewIntSetFrom([]int{1, 2, 3}) fmt.Println(intSet.Size()) intSet.Clear() fmt.Println(intSet.Size()) @@ -110,8 +110,8 @@ func ExampleIntSet_Clear() { // 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}, true) - s := gset.NewIntSetFrom([]int{1, 2, 3}, true) + intSet := gset.NewIntSetFrom([]int{1, 2, 3, 4, 5}) + s := gset.NewIntSetFrom([]int{1, 2, 3}) fmt.Println(s.Complement(intSet).Slice()) // May Output: @@ -136,8 +136,8 @@ func ExampleIntSet_Contains() { // 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}, true) - s2 := gset.NewIntSetFrom([]int{1, 2, 3, 4}, true) + s1 := gset.NewIntSetFrom([]int{1, 2, 3}) + s2 := gset.NewIntSetFrom([]int{1, 2, 3, 4}) fmt.Println(s2.Diff(s1).Slice()) // Output: @@ -146,12 +146,12 @@ func ExampleIntSet_Diff() { // Equal checks whether the two sets equal. func ExampleIntSet_Equal() { - s1 := gset.NewIntSetFrom([]int{1, 2, 3}, true) - s2 := gset.NewIntSetFrom([]int{1, 2, 3, 4}, true) + 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}, true) - s4 := gset.NewIntSetFrom([]int{1, 2, 3}, true) + s3 := gset.NewIntSetFrom([]int{1, 2, 3}) + s4 := gset.NewIntSetFrom([]int{1, 2, 3}) fmt.Println(s3.Equal(s4)) // Output: @@ -162,7 +162,7 @@ func ExampleIntSet_Equal() { // 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(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3}...) var s2 gset.IntSet s2.Add([]int{1, 2, 3, 4}...) @@ -174,7 +174,7 @@ func ExampleIntSet_Intersect() { // IsSubsetOf checks whether the current set is a sub-set of `other` func ExampleIntSet_IsSubsetOf() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) var s2 gset.IntSet s2.Add([]int{1, 2, 4}...) @@ -187,7 +187,7 @@ func ExampleIntSet_IsSubsetOf() { // 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(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) s1.Iterator(func(v int) bool { fmt.Println("Iterator", v) @@ -202,7 +202,7 @@ func ExampleIntSet_Iterator() { // Join joins items with a string `glue`. func ExampleIntSet_Join() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) fmt.Println(s1.Join(",")) @@ -212,7 +212,7 @@ func ExampleIntSet_Join() { // LockFunc locks writing with callback function `f`. func ExampleIntSet_LockFunc() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2}...) s1.LockFunc(func(m map[int]struct{}) { m[3] = struct{}{} @@ -233,7 +233,7 @@ func ExampleIntSet_MarshalJSON() { s := Student{ Id: 1, Name: "john", - Scores: gset.NewIntSetFrom([]int{100, 99, 98}, true), + Scores: gset.NewIntSetFrom([]int{100, 99, 98}), } b, _ := json.Marshal(s) fmt.Println(string(b)) @@ -244,10 +244,10 @@ func ExampleIntSet_MarshalJSON() { // Merge adds items from `others` sets into `set`. func ExampleIntSet_Merge() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) - s2 := gset.NewIntSet(true) + s2 := gset.NewIntSet() fmt.Println(s1.Merge(s2).Slice()) // May Output: @@ -256,7 +256,7 @@ func ExampleIntSet_Merge() { // Pops randomly pops an item from set. func ExampleIntSet_Pop() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) fmt.Println(s1.Pop()) @@ -268,7 +268,7 @@ func ExampleIntSet_Pop() { // Pops randomly pops `size` items from set. // It returns all items if size == -1. func ExampleIntSet_Pops() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) for _, v := range s1.Pops(2) { fmt.Println(v) @@ -281,7 +281,7 @@ func ExampleIntSet_Pops() { // RLockFunc locks reading with callback function `f`. func ExampleIntSet_RLockFunc() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) s1.RLockFunc(func(m map[int]struct{}) { fmt.Println(m) @@ -293,7 +293,7 @@ func ExampleIntSet_RLockFunc() { // Remove deletes `item` from set. func ExampleIntSet_Remove() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) s1.Remove(1) fmt.Println(s1.Slice()) @@ -304,7 +304,7 @@ func ExampleIntSet_Remove() { // Size returns the size of the set. func ExampleIntSet_Size() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) fmt.Println(s1.Size()) @@ -314,7 +314,7 @@ func ExampleIntSet_Size() { // Slice returns the a of items of the set as slice. func ExampleIntSet_Slice() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) fmt.Println(s1.Slice()) @@ -324,7 +324,7 @@ func ExampleIntSet_Slice() { // String returns items as a string, which implements like json.Marshal does. func ExampleIntSet_String() { - s1 := gset.NewIntSet(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) fmt.Println(s1.String()) @@ -335,7 +335,7 @@ func ExampleIntSet_String() { // 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(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) fmt.Println(s1.Sum()) @@ -346,9 +346,9 @@ func ExampleIntSet_Sum() { // 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(true) + s1 := gset.NewIntSet() s1.Add([]int{1, 2, 3, 4}...) - s2 := gset.NewIntSet(true) + s2 := gset.NewIntSet() s2.Add([]int{1, 2, 4}...) fmt.Println(s1.Union(s2).Slice()) @@ -391,14 +391,14 @@ func ExampleIntSet_UnmarshalValue() { // Walk applies a user supplied function `f` to every item of set. func ExampleIntSet_Walk() { var ( - set gset.IntSet - names = g.SliceInt{1, 0} - prefix = 10 + 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 prefix + item + return delta + item }) fmt.Println(set.Slice()) From 42c4b32720925df525be5b1e822aa46719da7c2a Mon Sep 17 00:00:00 2001 From: John Guo Date: Sun, 7 Nov 2021 00:16:14 +0800 Subject: [PATCH 21/22] add gconv.ScanList --- .../gdb_z_mysql_association_scanlist_test.go | 2 +- internal/utils/utils_list.go | 37 +++ internal/utils/utils_map.go | 26 ++ text/gstr/gstr.go | 9 +- util/gconv/gconv_scan.go | 141 +++++---- util/gconv/gconv_z_unit_scan_test.go | 282 ++++++++++++++++++ util/gutil/gutil_dump.go | 7 +- util/gutil/gutil_list.go | 7 + util/gutil/gutil_map.go | 14 +- 9 files changed, 438 insertions(+), 87 deletions(-) create mode 100644 internal/utils/utils_list.go create mode 100644 internal/utils/utils_map.go diff --git a/database/gdb/gdb_z_mysql_association_scanlist_test.go b/database/gdb/gdb_z_mysql_association_scanlist_test.go index dee305cfc..5016d60a4 100644 --- a/database/gdb/gdb_z_mysql_association_scanlist_test.go +++ b/database/gdb/gdb_z_mysql_association_scanlist_test.go @@ -1776,7 +1776,7 @@ CREATE TABLE %s ( 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 diff --git a/internal/utils/utils_list.go b/internal/utils/utils_list.go new file mode 100644 index 000000000..355ad9f8e --- /dev/null +++ b/internal/utils/utils_list.go @@ -0,0 +1,37 @@ +// 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 utils + +import "fmt" + +// ListToMapByKey converts `list` to a map[string]interface{} of which key is specified by `key`. +// Note that the item value may be type of slice. +func ListToMapByKey(list []map[string]interface{}, key string) map[string]interface{} { + var ( + s = "" + m = make(map[string]interface{}) + tempMap = make(map[string][]interface{}) + hasMultiValues bool + ) + for _, item := range list { + if k, ok := item[key]; ok { + s = fmt.Sprintf(`%v`, k) + tempMap[s] = append(tempMap[s], item) + if len(tempMap[s]) > 1 { + hasMultiValues = true + } + } + } + for k, v := range tempMap { + if hasMultiValues { + m[k] = v + } else { + m[k] = v[0] + } + } + return m +} diff --git a/internal/utils/utils_map.go b/internal/utils/utils_map.go new file mode 100644 index 000000000..6cb1b6067 --- /dev/null +++ b/internal/utils/utils_map.go @@ -0,0 +1,26 @@ +// 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 utils + +// MapPossibleItemByKey tries to find the possible key-value pair for given key ignoring cases and symbols. +// +// Note that this function might be of low performance. +func MapPossibleItemByKey(data map[string]interface{}, key string) (foundKey string, foundValue interface{}) { + if len(data) == 0 { + return + } + if v, ok := data[key]; ok { + return key, v + } + // Loop checking. + for k, v := range data { + if EqualFoldWithoutChars(k, key) { + return k, v + } + } + return "", nil +} diff --git a/text/gstr/gstr.go b/text/gstr/gstr.go index 7a08c0cf4..bc7b4d7bb 100644 --- a/text/gstr/gstr.go +++ b/text/gstr/gstr.go @@ -327,14 +327,7 @@ func Split(str, delimiter string) []string { // and calls Trim to every element of this array. It ignores the elements // which are empty after Trim. func SplitAndTrim(str, delimiter string, characterMask ...string) []string { - array := make([]string, 0) - for _, v := range strings.Split(str, delimiter) { - v = Trim(v, characterMask...) - if v != "" { - array = append(array, v) - } - } - return array + return utils.SplitAndTrim(str, delimiter, characterMask...) } // Join concatenates the elements of `array` to create a single string. The separator string diff --git a/util/gconv/gconv_scan.go b/util/gconv/gconv_scan.go index 76ebcb149..5472bdd83 100644 --- a/util/gconv/gconv_scan.go +++ b/util/gconv/gconv_scan.go @@ -11,8 +11,7 @@ import ( "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/gutil" + "github.com/gogf/gf/v2/internal/utils" "reflect" ) @@ -42,7 +41,18 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) } pointerKind = pointerType.Kind() if pointerKind != reflect.Ptr { - return gerror.NewCodef(gcode.CodeInvalidParameter, "params should be type of pointer, but got type: %v", pointerKind) + if pointerValue.CanAddr() { + pointerValue = pointerValue.Addr() + pointerType = pointerValue.Type() + pointerKind = pointerType.Kind() + } else { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + "params should be type of pointer, but got type: %v", + pointerType, + ) + } + } // Direct assignment checks! var ( @@ -99,7 +109,7 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) } } -// ScanList converts `data` to struct slice which contains other complex struct attributes. +// ScanList converts `structSlice` to struct slice which contains other complex struct attributes. // Note that the parameter `structSlicePointer` should be type of *[]struct/*[]*struct. // // Usage example 1: Normal attribute struct relation: @@ -123,11 +133,11 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) // UserScores []*EntityUserScores // } // 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") +// ScanList(records, &users, "User") +// ScanList(records, &users, "User", "uid") +// ScanList(records, &users, "UserDetail", "User", "uid:Uid") +// ScanList(records, &users, "UserScores", "User", "uid:Uid") +// ScanList(records, &users, "UserScores", "User", "uid") // // // Usage example 2: Embedded attribute struct relation: @@ -151,10 +161,21 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) // } // // var users []*Entity -// ScanList(&users) -// ScanList(&users, "UserDetail", "uid") -// ScanList(&users, "UserScores", "uid") -func ScanList(data interface{}, structSlicePointer interface{}, bindToAttrName string, relationAttrNameAndFields ...string) (err error) { +// ScanList(records, &users) +// ScanList(records, &users, "UserDetail", "uid") +// ScanList(records, &users, "UserScores", "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 - not the attribute name of the bound to target. In the example codes, it's attribute +// name "Uid" of "User" of entity "Entity". 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 ScanList(structSlice interface{}, structSlicePointer interface{}, bindToAttrName string, relationAttrNameAndFields ...string) (err error) { var ( relationAttrName string relationFields string @@ -166,15 +187,16 @@ func ScanList(data interface{}, structSlicePointer interface{}, bindToAttrName s case 1: relationFields = relationAttrNameAndFields[0] } - return doScanList(data, structSlicePointer, bindToAttrName, relationAttrName, relationFields) + return doScanList(structSlice, structSlicePointer, bindToAttrName, relationAttrName, relationFields) } -// doScanList converts `data` to struct slice which contains other complex struct attributes recursively. -// 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. +// doScanList converts `structSlice` to struct slice which contains other complex struct attributes recursively. // Note that the parameter `structSlicePointer` should be type of *[]struct/*[]*struct. -func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName, relationAttrName, relationFields string) (err error) { - if data == nil { +func doScanList(structSlice interface{}, structSlicePointer interface{}, bindToAttrName, relationAttrName, relationFields string) (err error) { + var ( + maps = Maps(structSlice) + ) + if len(maps) == 0 { return nil } // Necessary checks for parameters. @@ -210,6 +232,19 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName reflectKind, ) } + length := len(maps) + if length == 0 { + // The pointed slice is not empty. + if reflectValue.Len() > 0 { + // It here checks if it has struct item, which is already initialized. + // It then returns error to warn the developer its empty and no conversion. + if v := reflectValue.Index(0); v.Kind() != reflect.Ptr { + return sql.ErrNoRows + } + } + // Do nothing for empty struct slice. + return nil + } var ( arrayValue reflect.Value // Like: []*Entity arrayItemType reflect.Type // Like: *Entity @@ -226,17 +261,17 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName // Relation variables. var ( - relationDataMap map[string]Value + relationDataMap map[string]interface{} relationFromFieldName string // Eg: relationKV: id:uid -> id relationBindToFieldName string // Eg: relationKV: id:uid -> uid ) if len(relationFields) > 0 { // The relation key string of table filed name and attribute name // can be joined with char '=' or ':'. - array := gstr.SplitAndTrim(relationFields, "=") + array := utils.SplitAndTrim(relationFields, "=") if len(array) == 1 { // Compatible with old splitting char ':'. - array = gstr.SplitAndTrim(relationFields, ":") + array = utils.SplitAndTrim(relationFields, ":") } if len(array) == 1 { // The relation names are the same. @@ -249,7 +284,7 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName // uid:UserId relationFromFieldName = array[0] relationBindToFieldName = array[1] - if key, _ := gutil.MapPossibleItemByKey(result[0].Map(), relationFromFieldName); key == "" { + if key, _ := utils.MapPossibleItemByKey(maps[0], relationFromFieldName); key == "" { return gerror.NewCodef( gcode.CodeInvalidParameter, `cannot find possible related table field name "%s" from given relation fields "%s"`, @@ -267,7 +302,7 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName } if relationFromFieldName != "" { // Note that the value might be type of slice. - relationDataMap = result.MapKeyValue(relationFromFieldName) + relationDataMap = utils.ListToMapByKey(maps, relationFromFieldName) } if len(relationDataMap) == 0 { return gerror.NewCodef( @@ -353,7 +388,7 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName RecursiveOption: structs.RecursiveOptionEmbeddedNoTag, }) ) - if key, _ := gutil.MapPossibleItemByKey(gconv.Map(filedMap), relationBindToFieldName); key == "" { + if key, _ := utils.MapPossibleItemByKey(Map(filedMap), relationBindToFieldName); key == "" { return gerror.NewCodef( gcode.CodeInvalidParameter, `cannot find possible related attribute name "%s" from given relation fields "%s"`, @@ -371,19 +406,15 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName if len(relationDataMap) > 0 { relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) if relationFromAttrField.IsValid() { - results := make(Result, 0) - for _, v := range relationDataMap[gconv.String(relationFromAttrField.Interface())].Slice() { - results = append(results, v.(Record)) + //results := make(Result, 0) + results := make([]interface{}, 0) + for _, v := range SliceAny(relationDataMap[String(relationFromAttrField.Interface())]) { + item := v + results = append(results, item) } - if err = results.Structs(bindToAttrValue.Addr()); err != nil { + if err = Structs(results, bindToAttrValue.Addr()); err != nil { return err } - // Recursively Scan. - if model != nil { - if err = model.doWithScanStructs(bindToAttrValue.Addr()); err != nil { - return nil - } - } } else { // Maybe the attribute does not exist yet. return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) @@ -406,17 +437,17 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName if len(relationDataMap) > 0 { relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) if relationFromAttrField.IsValid() { - v := relationDataMap[gconv.String(relationFromAttrField.Interface())] + v := relationDataMap[String(relationFromAttrField.Interface())] if v == nil { // There's no relational data. continue } - if v.IsSlice() { - if err = v.Slice()[0].(Record).Struct(element); err != nil { + if utils.IsSlice(v) { + if err = Struct(SliceAny(v)[0], element); err != nil { return err } } else { - if err = v.Val().(Record).Struct(element); err != nil { + if err = Struct(v, element); err != nil { return err } } @@ -425,22 +456,16 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) } } else { - if i >= len(result) { + if i >= len(maps) { // There's no relational data. continue } - v := result[i] + v := maps[i] if v == nil { // There's no relational data. continue } - if err = v.Struct(element); err != nil { - return err - } - } - // Recursively Scan. - if model != nil { - if err = model.doWithScanStruct(element); err != nil { + if err = Struct(v, element); err != nil { return err } } @@ -450,17 +475,17 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName if len(relationDataMap) > 0 { relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToFieldName) if relationFromAttrField.IsValid() { - relationDataItem := relationDataMap[gconv.String(relationFromAttrField.Interface())] + relationDataItem := relationDataMap[String(relationFromAttrField.Interface())] if relationDataItem == nil { // There's no relational data. continue } - if relationDataItem.IsSlice() { - if err = relationDataItem.Slice()[0].(Record).Struct(bindToAttrValue); err != nil { + if utils.IsSlice(relationDataItem) { + if err = Struct(SliceAny(relationDataItem)[0], bindToAttrValue); err != nil { return err } } else { - if err = relationDataItem.Val().(Record).Struct(bindToAttrValue); err != nil { + if err = Struct(relationDataItem, bindToAttrValue); err != nil { return err } } @@ -469,22 +494,16 @@ func doScanList(data interface{}, structSlicePointer interface{}, bindToAttrName return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid relation fields specified: "%v"`, relationFields) } } else { - if i >= len(result) { + if i >= len(maps) { // There's no relational data. continue } - relationDataItem := result[i] + relationDataItem := maps[i] if relationDataItem == nil { // There's no relational data. continue } - if err = relationDataItem.Struct(bindToAttrValue); err != nil { - return err - } - } - // Recursively Scan. - if model != nil { - if err = model.doWithScanStruct(bindToAttrValue); err != nil { + if err = Struct(relationDataItem, bindToAttrValue); err != nil { return err } } diff --git a/util/gconv/gconv_z_unit_scan_test.go b/util/gconv/gconv_z_unit_scan_test.go index 65248bced..e34f91d99 100644 --- a/util/gconv/gconv_z_unit_scan_test.go +++ b/util/gconv/gconv_z_unit_scan_test.go @@ -319,3 +319,285 @@ func Test_Scan_SameType_Just_Assign(t *testing.T) { t.Assert(*m1["int"], *m2["int"]) }) } + +func Test_ScanList_Basic(t *testing.T) { + // Struct attribute. + gtest.C(t, func(t *gtest.T) { + 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 { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + + var ( + err error + entities []Entity + entityUsers = []EntityUser{ + {Uid: 1, Name: "name1"}, + {Uid: 2, Name: "name2"}, + {Uid: 3, Name: "name3"}, + } + userDetails = []EntityUserDetail{ + {Uid: 1, Address: "address1"}, + {Uid: 2, Address: "address2"}, + } + userScores = []EntityUserScores{ + {Id: 10, Uid: 1, Score: 100}, + {Id: 11, Uid: 1, Score: 60}, + {Id: 20, Uid: 2, Score: 99}, + } + ) + err = gconv.ScanList(entityUsers, &entities, "User") + t.AssertNil(err) + + err = gconv.ScanList(userDetails, &entities, "UserDetail", "User", "uid") + t.AssertNil(err) + + err = gconv.ScanList(userScores, &entities, "UserScores", "User", "uid") + t.AssertNil(err) + + t.Assert(len(entities), 3) + t.Assert(entities[0].User, entityUsers[0]) + t.Assert(entities[1].User, entityUsers[1]) + t.Assert(entities[2].User, entityUsers[2]) + + t.Assert(entities[0].UserDetail, userDetails[0]) + t.Assert(entities[1].UserDetail, userDetails[1]) + t.Assert(entities[2].UserDetail, EntityUserDetail{}) + + t.Assert(len(entities[0].UserScores), 2) + t.Assert(entities[0].UserScores[0], userScores[0]) + t.Assert(entities[0].UserScores[1], userScores[1]) + + t.Assert(len(entities[1].UserScores), 1) + t.Assert(entities[1].UserScores[0], userScores[2]) + + t.Assert(len(entities[2].UserScores), 0) + }) + // Pointer attribute. + gtest.C(t, func(t *gtest.T) { + 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 { + User *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + var ( + err error + entities []*Entity + entityUsers = []*EntityUser{ + {Uid: 1, Name: "name1"}, + {Uid: 2, Name: "name2"}, + {Uid: 3, Name: "name3"}, + } + userDetails = []*EntityUserDetail{ + {Uid: 1, Address: "address1"}, + {Uid: 2, Address: "address2"}, + } + userScores = []*EntityUserScores{ + {Id: 10, Uid: 1, Score: 100}, + {Id: 11, Uid: 1, Score: 60}, + {Id: 20, Uid: 2, Score: 99}, + } + ) + err = gconv.ScanList(entityUsers, &entities, "User") + t.AssertNil(err) + + err = gconv.ScanList(userDetails, &entities, "UserDetail", "User", "uid") + t.AssertNil(err) + + err = gconv.ScanList(userScores, &entities, "UserScores", "User", "uid") + t.AssertNil(err) + + t.Assert(len(entities), 3) + t.Assert(entities[0].User, entityUsers[0]) + t.Assert(entities[1].User, entityUsers[1]) + t.Assert(entities[2].User, entityUsers[2]) + + t.Assert(entities[0].UserDetail, userDetails[0]) + t.Assert(entities[1].UserDetail, userDetails[1]) + t.Assert(entities[2].UserDetail, nil) + + t.Assert(len(entities[0].UserScores), 2) + t.Assert(entities[0].UserScores[0], userScores[0]) + t.Assert(entities[0].UserScores[1], userScores[1]) + + t.Assert(len(entities[1].UserScores), 1) + t.Assert(entities[1].UserScores[0], userScores[2]) + + t.Assert(len(entities[2].UserScores), 0) + }) +} + +func Test_ScanList_Embedded(t *testing.T) { + // Struct attribute. + gtest.C(t, func(t *gtest.T) { + 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 ( + err error + entities []Entity + entityUsers = []EntityUser{ + {Uid: 1, Name: "name1"}, + {Uid: 2, Name: "name2"}, + {Uid: 3, Name: "name3"}, + } + userDetails = []EntityUserDetail{ + {Uid: 1, Address: "address1"}, + {Uid: 2, Address: "address2"}, + } + userScores = []EntityUserScores{ + {Id: 10, Uid: 1, Score: 100}, + {Id: 11, Uid: 1, Score: 60}, + {Id: 20, Uid: 2, Score: 99}, + } + ) + err = gconv.Scan(entityUsers, &entities) + t.AssertNil(err) + + err = gconv.ScanList(userDetails, &entities, "UserDetail", "uid") + t.AssertNil(err) + + err = gconv.ScanList(userScores, &entities, "UserScores", "uid") + t.AssertNil(err) + + t.Assert(len(entities), 3) + t.Assert(entities[0].EntityUser, entityUsers[0]) + t.Assert(entities[1].EntityUser, entityUsers[1]) + t.Assert(entities[2].EntityUser, entityUsers[2]) + + t.Assert(entities[0].UserDetail, userDetails[0]) + t.Assert(entities[1].UserDetail, userDetails[1]) + t.Assert(entities[2].UserDetail, EntityUserDetail{}) + + t.Assert(len(entities[0].UserScores), 2) + t.Assert(entities[0].UserScores[0], userScores[0]) + t.Assert(entities[0].UserScores[1], userScores[1]) + + t.Assert(len(entities[1].UserScores), 1) + t.Assert(entities[1].UserScores[0], userScores[2]) + + t.Assert(len(entities[2].UserScores), 0) + }) + // Pointer attribute. + gtest.C(t, func(t *gtest.T) { + 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 ( + err error + entities []Entity + entityUsers = []EntityUser{ + {Uid: 1, Name: "name1"}, + {Uid: 2, Name: "name2"}, + {Uid: 3, Name: "name3"}, + } + userDetails = []EntityUserDetail{ + {Uid: 1, Address: "address1"}, + {Uid: 2, Address: "address2"}, + } + userScores = []EntityUserScores{ + {Id: 10, Uid: 1, Score: 100}, + {Id: 11, Uid: 1, Score: 60}, + {Id: 20, Uid: 2, Score: 99}, + } + ) + err = gconv.Scan(entityUsers, &entities) + t.AssertNil(err) + + err = gconv.ScanList(userDetails, &entities, "UserDetail", "uid") + t.AssertNil(err) + + err = gconv.ScanList(userScores, &entities, "UserScores", "uid") + t.AssertNil(err) + + t.Assert(len(entities), 3) + t.Assert(entities[0].EntityUser, entityUsers[0]) + t.Assert(entities[1].EntityUser, entityUsers[1]) + t.Assert(entities[2].EntityUser, entityUsers[2]) + + t.Assert(entities[0].UserDetail, userDetails[0]) + t.Assert(entities[1].UserDetail, userDetails[1]) + t.Assert(entities[2].UserDetail, nil) + + t.Assert(len(entities[0].UserScores), 2) + t.Assert(entities[0].UserScores[0], userScores[0]) + t.Assert(entities[0].UserScores[1], userScores[1]) + + t.Assert(len(entities[1].UserScores), 1) + t.Assert(entities[1].UserScores[0], userScores[2]) + + t.Assert(len(entities[2].UserScores), 0) + }) +} diff --git a/util/gutil/gutil_dump.go b/util/gutil/gutil_dump.go index 06ed56fd5..0403ca55d 100644 --- a/util/gutil/gutil_dump.go +++ b/util/gutil/gutil_dump.go @@ -10,7 +10,6 @@ import ( "bytes" "fmt" "github.com/gogf/gf/v2/internal/structs" - "github.com/gogf/gf/v2/text/gstr" "reflect" "strings" ) @@ -151,7 +150,7 @@ func doExport(value interface{}, indent string, buffer *bytes.Buffer, option doE "%s%v:%s", newIndent, mapKeyStr, - gstr.Repeat(" ", maxSpaceNum-tmpSpaceNum+1), + strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1), )) } else { buffer.WriteString(fmt.Sprintf( @@ -159,7 +158,7 @@ func doExport(value interface{}, indent string, buffer *bytes.Buffer, option doE newIndent, mapKey.Type().String(), mapKeyStr, - gstr.Repeat(" ", maxSpaceNum-tmpSpaceNum+1), + strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1), )) } doExport(reflectValue.MapIndex(mapKey).Interface(), newIndent, buffer, option) @@ -202,7 +201,7 @@ func doExport(value interface{}, indent string, buffer *bytes.Buffer, option doE "%s%s:%s", newIndent, field.Name(), - gstr.Repeat(" ", maxSpaceNum-tmpSpaceNum+1), + strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1), )) doExport(field.Value.Interface(), newIndent, buffer, option) buffer.WriteString(",\n") diff --git a/util/gutil/gutil_list.go b/util/gutil/gutil_list.go index 14fd8e2f6..12a8735e3 100644 --- a/util/gutil/gutil_list.go +++ b/util/gutil/gutil_list.go @@ -7,6 +7,7 @@ package gutil import ( + "github.com/gogf/gf/v2/internal/utils" "reflect" ) @@ -130,3 +131,9 @@ func ListItemValuesUnique(list interface{}, key string, subKey ...interface{}) [ } return values } + +// ListToMapByKey converts `list` to a map[string]interface{} of which key is specified by `key`. +// Note that the item value may be type of slice. +func ListToMapByKey(list []map[string]interface{}, key string) map[string]interface{} { + return utils.ListToMapByKey(list, key) +} diff --git a/util/gutil/gutil_map.go b/util/gutil/gutil_map.go index 1a9b96029..2b5246e91 100644 --- a/util/gutil/gutil_map.go +++ b/util/gutil/gutil_map.go @@ -67,19 +67,7 @@ func MapMergeCopy(src ...map[string]interface{}) (copy map[string]interface{}) { // // Note that this function might be of low performance. func MapPossibleItemByKey(data map[string]interface{}, key string) (foundKey string, foundValue interface{}) { - if len(data) == 0 { - return - } - if v, ok := data[key]; ok { - return key, v - } - // Loop checking. - for k, v := range data { - if utils.EqualFoldWithoutChars(k, key) { - return k, v - } - } - return "", nil + return utils.MapPossibleItemByKey(data, key) } // MapContainsPossibleKey checks if the given `key` is contained in given map `data`. From 3ca2cad449565ee66007dda3796518585c086bd0 Mon Sep 17 00:00:00 2001 From: John Guo Date: Sun, 7 Nov 2021 00:32:16 +0800 Subject: [PATCH 22/22] improve gutil.Dump --- util/gutil/gutil_dump.go | 38 +++++++- util/gutil/gutil_z_unit_dump_test.go | 128 +++++++++++++++++++++++++++ util/gutil/gutil_z_unit_test.go | 117 ------------------------ 3 files changed, 163 insertions(+), 120 deletions(-) create mode 100755 util/gutil/gutil_z_unit_dump_test.go diff --git a/util/gutil/gutil_dump.go b/util/gutil/gutil_dump.go index 0403ca55d..0e331426f 100644 --- a/util/gutil/gutil_dump.go +++ b/util/gutil/gutil_dump.go @@ -10,10 +10,21 @@ import ( "bytes" "fmt" "github.com/gogf/gf/v2/internal/structs" + "github.com/gogf/gf/v2/text/gstr" "reflect" "strings" ) +// iString is used for type assert api for String(). +type iString interface { + String() string +} + +// iMarshalJSON is the interface for custom Json marshaling. +type iMarshalJSON interface { + MarshalJSON() ([]byte, error) +} + // ExportOption specifies the behavior of function Export. type ExportOption struct { WithoutType bool // WithoutType specifies exported content has no type information. @@ -172,10 +183,31 @@ func doExport(value interface{}, indent string, buffer *bytes.Buffer, option doE RecursiveOption: structs.RecursiveOptionEmbeddedNoTag, }) if len(structFields) == 0 { - if option.WithoutType { - buffer.WriteString("{}") + var ( + structContentStr = "" + attributeCountStr = "0" + ) + if v, ok := value.(iString); ok { + structContentStr = v.String() + } else if v, ok := value.(iMarshalJSON); ok { + b, _ := v.MarshalJSON() + structContentStr = string(b) + } + if structContentStr == "" { + structContentStr = "{}" } else { - buffer.WriteString(fmt.Sprintf("%s(0) {}", reflectTypeName)) + structContentStr = fmt.Sprintf(`"%s"`, gstr.AddSlashes(structContentStr)) + attributeCountStr = fmt.Sprintf(`%d`, len(structContentStr)-2) + } + if option.WithoutType { + buffer.WriteString(structContentStr) + } else { + buffer.WriteString(fmt.Sprintf( + "%s(%s) %s", + reflectTypeName, + attributeCountStr, + structContentStr, + )) } return } diff --git a/util/gutil/gutil_z_unit_dump_test.go b/util/gutil/gutil_z_unit_dump_test.go new file mode 100755 index 000000000..236d07add --- /dev/null +++ b/util/gutil/gutil_z_unit_dump_test.go @@ -0,0 +1,128 @@ +// 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 gutil_test + +import ( + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" + "testing" + + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/gutil" +) + +func Test_Dump(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"` + } + type SetSpecInfo struct { + StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"` + Shards int32 `des:"shards 分片数" sum:"Shards Summary"` + Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"` + } + type CreateResourceReq struct { + CommonReq + gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"` + Name string + CreatedAt *gtime.Time + SetMap map[string]*SetSpecInfo + SetSlice []SetSpecInfo + Handler ghttp.HandlerFunc + internal string + } + req := &CreateResourceReq{ + CommonReq: CommonReq{ + AppId: 12345678, + ResourceId: "tdchqy-xxx", + }, + Name: "john", + CreatedAt: gtime.Now(), + SetMap: map[string]*SetSpecInfo{ + "test1": { + StorageType: "ssd", + Shards: 2, + Params: []string{"a", "b", "c"}, + }, + "test2": { + StorageType: "hssd", + Shards: 10, + Params: []string{}, + }, + }, + SetSlice: []SetSpecInfo{ + { + StorageType: "hssd", + Shards: 10, + Params: []string{"h"}, + }, + }, + } + gtest.C(t, func(t *gtest.T) { + gutil.Dump(map[int]int{ + 100: 100, + }) + gutil.Dump(req) + }) +} + +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"` + } + type SetSpecInfo struct { + StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"` + Shards int32 `des:"shards 分片数" sum:"Shards Summary"` + Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"` + } + type CreateResourceReq struct { + CommonReq + gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"` + Name string + CreatedAt *gtime.Time + SetMap map[string]*SetSpecInfo `v:"required" des:"配置Map"` + SetSlice []SetSpecInfo `v:"required" des:"配置Slice"` + Handler ghttp.HandlerFunc + internal string + } + req := &CreateResourceReq{ + CommonReq: CommonReq{ + AppId: 12345678, + ResourceId: "tdchqy-xxx", + }, + Name: "john", + CreatedAt: gtime.Now(), + SetMap: map[string]*SetSpecInfo{ + "test1": { + StorageType: "ssd", + Shards: 2, + Params: []string{"a", "b", "c"}, + }, + "test2": { + StorageType: "hssd", + Shards: 10, + Params: []string{}, + }, + }, + SetSlice: []SetSpecInfo{ + { + StorageType: "hssd", + Shards: 10, + Params: []string{"h"}, + }, + }, + } + gtest.C(t, func(t *gtest.T) { + gutil.DumpWithType(map[int]int{ + 100: 100, + }) + gutil.DumpWithType(req) + gutil.DumpWithType([][]byte{[]byte("hello")}) + }) +} diff --git a/util/gutil/gutil_z_unit_test.go b/util/gutil/gutil_z_unit_test.go index 253b89373..0459ad4f7 100755 --- a/util/gutil/gutil_z_unit_test.go +++ b/util/gutil/gutil_z_unit_test.go @@ -8,129 +8,12 @@ package gutil_test import ( "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/net/ghttp" - "github.com/gogf/gf/v2/util/gmeta" "testing" "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/gutil" ) -func Test_Dump(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"` - } - type SetSpecInfo struct { - StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"` - Shards int32 `des:"shards 分片数" sum:"Shards Summary"` - Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"` - } - type CreateResourceReq struct { - CommonReq - gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"` - Name string `des:"实例名称"` - Product string `des:"业务类型"` - Region string `v:"required" des:"区域"` - SetMap map[string]*SetSpecInfo `v:"required" des:"配置Map"` - SetSlice []SetSpecInfo `v:"required" des:"配置Slice"` - Handler ghttp.HandlerFunc - internal string - } - req := &CreateResourceReq{ - CommonReq: CommonReq{ - AppId: 12345678, - ResourceId: "tdchqy-xxx", - }, - Name: "john", - Product: "goframe", - Region: "cd", - SetMap: map[string]*SetSpecInfo{ - "test1": { - StorageType: "ssd", - Shards: 2, - Params: []string{"a", "b", "c"}, - }, - "test2": { - StorageType: "hssd", - Shards: 10, - Params: []string{}, - }, - }, - SetSlice: []SetSpecInfo{ - { - StorageType: "hssd", - Shards: 10, - Params: []string{"h"}, - }, - }, - } - gtest.C(t, func(t *gtest.T) { - gutil.Dump(map[int]int{ - 100: 100, - }) - gutil.Dump(req) - }) -} - -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"` - } - type SetSpecInfo struct { - StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"` - Shards int32 `des:"shards 分片数" sum:"Shards Summary"` - Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"` - } - type CreateResourceReq struct { - CommonReq - gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"` - Name string `des:"实例名称"` - Product string `des:"业务类型"` - Region string `v:"required" des:"区域"` - SetMap map[string]*SetSpecInfo `v:"required" des:"配置Map"` - SetSlice []SetSpecInfo `v:"required" des:"配置Slice"` - Handler ghttp.HandlerFunc - internal string - } - req := &CreateResourceReq{ - CommonReq: CommonReq{ - AppId: 12345678, - ResourceId: "tdchqy-xxx", - }, - Name: "john", - Product: "goframe", - Region: "cd", - SetMap: map[string]*SetSpecInfo{ - "test1": { - StorageType: "ssd", - Shards: 2, - Params: []string{"a", "b", "c"}, - }, - "test2": { - StorageType: "hssd", - Shards: 10, - Params: []string{}, - }, - }, - SetSlice: []SetSpecInfo{ - { - StorageType: "hssd", - Shards: 10, - Params: []string{"h"}, - }, - }, - } - gtest.C(t, func(t *gtest.T) { - gutil.DumpWithType(map[int]int{ - 100: 100, - }) - gutil.DumpWithType(req) - gutil.DumpWithType([][]byte{[]byte("hello")}) - }) -} - func Test_Try(t *testing.T) { gtest.C(t, func(t *gtest.T) { s := `gutil Try test`