diff --git a/util/gtag/gtag.go b/util/gtag/gtag.go index 68d915806..058159386 100644 --- a/util/gtag/gtag.go +++ b/util/gtag/gtag.go @@ -11,8 +11,9 @@ package gtag import ( - "fmt" "regexp" + + "github.com/gogf/gf/v2/errors/gerror" ) var ( @@ -21,20 +22,30 @@ var ( ) // Set sets tag content for specified name. +// Note that it panics if `name` already exists. func Set(name, value string) { if _, ok := data[name]; ok { - panic(fmt.Sprintf(`value for tag "%s" already exists`, name)) + panic(gerror.Newf(`value for tag name "%s" already exists`, name)) } data[name] = value } +// SetOver performs as Set, but it overwrites the old value if `name` already exists. +func SetOver(name, value string) { + data[name] = value +} + // Sets sets multiple tag content by map. func Sets(m map[string]string) { for k, v := range m { - if _, ok := data[k]; ok { - panic(fmt.Sprintf(`value for tag "%s" already exists`, k)) - } - data[k] = v + Set(k, v) + } +} + +// SetsOver performs as Sets, but it overwrites the old value if `name` already exists. +func SetsOver(m map[string]string) { + for k, v := range m { + SetOver(k, v) } } @@ -46,8 +57,8 @@ func Get(name string) string { // Parse parses and returns the content by replacing all tag name variable to // its content for given `content`. // Eg: -// If "Demo:content" in tag mapping, -// Parse(`This is {Demo}`) -> `This is content`. +// gtag.Set("demo", "content") +// Parse(`This is {demo}`) -> `This is content`. func Parse(content string) string { return regex.ReplaceAllStringFunc(content, func(s string) string { if v, ok := data[s[1:len(s)-1]]; ok { diff --git a/util/gtag/gtag_z_unit_test.go b/util/gtag/gtag_z_unit_test.go index d38c9cb81..a8e8160c4 100644 --- a/util/gtag/gtag_z_unit_test.go +++ b/util/gtag/gtag_z_unit_test.go @@ -11,26 +11,56 @@ import ( "testing" "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/gtag" + "github.com/gogf/gf/v2/util/guid" ) func Test_Set_Get(t *testing.T) { gtest.C(t, func(t *gtest.T) { - k := gtime.TimestampNanoStr() - v := gtime.TimestampNanoStr() + k := guid.S() + v := guid.S() gtag.Set(k, v) t.Assert(gtag.Get(k), v) }) } +func Test_SetOver_Get(t *testing.T) { + // panic by Set + gtest.C(t, func(t *gtest.T) { + var ( + k = guid.S() + v1 = guid.S() + v2 = guid.S() + ) + gtag.Set(k, v1) + t.Assert(gtag.Get(k), v1) + defer func() { + t.AssertNE(recover(), nil) + }() + gtag.Set(k, v2) + }) + gtest.C(t, func(t *gtest.T) { + var ( + k = guid.S() + v1 = guid.S() + v2 = guid.S() + ) + gtag.SetOver(k, v1) + t.Assert(gtag.Get(k), v1) + gtag.SetOver(k, v2) + t.Assert(gtag.Get(k), v2) + }) +} + func Test_Sets_Get(t *testing.T) { gtest.C(t, func(t *gtest.T) { - k1 := gtime.TimestampNanoStr() - k2 := gtime.TimestampNanoStr() - v1 := gtime.TimestampNanoStr() - v2 := gtime.TimestampNanoStr() + var ( + k1 = guid.S() + k2 = guid.S() + v1 = guid.S() + v2 = guid.S() + ) gtag.Sets(g.MapStrStr{ k1: v1, k2: v2, @@ -40,13 +70,60 @@ func Test_Sets_Get(t *testing.T) { }) } +func Test_SetsOver_Get(t *testing.T) { + // panic by Sets + gtest.C(t, func(t *gtest.T) { + var ( + k1 = guid.S() + k2 = guid.S() + v1 = guid.S() + v2 = guid.S() + v3 = guid.S() + ) + gtag.Sets(g.MapStrStr{ + k1: v1, + k2: v2, + }) + t.Assert(gtag.Get(k1), v1) + t.Assert(gtag.Get(k2), v2) + defer func() { + t.AssertNE(recover(), nil) + }() + gtag.Sets(g.MapStrStr{ + k1: v3, + k2: v3, + }) + }) + gtest.C(t, func(t *gtest.T) { + var ( + k1 = guid.S() + k2 = guid.S() + v1 = guid.S() + v2 = guid.S() + v3 = guid.S() + ) + gtag.SetsOver(g.MapStrStr{ + k1: v1, + k2: v2, + }) + t.Assert(gtag.Get(k1), v1) + t.Assert(gtag.Get(k2), v2) + gtag.SetsOver(g.MapStrStr{ + k1: v3, + k2: v3, + }) + t.Assert(gtag.Get(k1), v3) + t.Assert(gtag.Get(k2), v3) + }) +} + func Test_Parse(t *testing.T) { gtest.C(t, func(t *gtest.T) { var ( - k1 = gtime.TimestampNanoStr() - k2 = gtime.TimestampNanoStr() - v1 = gtime.TimestampNanoStr() - v2 = gtime.TimestampNanoStr() + k1 = guid.S() + k2 = guid.S() + v1 = guid.S() + v2 = guid.S() content = fmt.Sprintf(`this is {%s} and {%s}`, k1, k2) expect = fmt.Sprintf(`this is %s and %s`, v1, v2) ) diff --git a/util/guid/guid.go b/util/guid/guid.go index cea74ab19..041481e56 100644 --- a/util/guid/guid.go +++ b/util/guid/guid.go @@ -13,6 +13,8 @@ import ( "github.com/gogf/gf/v2/container/gtype" "github.com/gogf/gf/v2/encoding/ghash" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/net/gipv4" "github.com/gogf/gf/v2/util/grand" ) @@ -67,7 +69,7 @@ func init() { // Note that: // 1. The returned length is fixed to 32 bytes for performance purpose. // 2. The custom parameter `data` composed should have unique attribute in your -// business situation. +// business scenario. func S(data ...[]byte) string { var ( b = make([]byte, 32) @@ -92,7 +94,10 @@ func S(data ...[]byte) string { copy(b[n+12:], getSequence()) copy(b[n+12+3:], getRandomStr(32-n-12-3)) } else { - panic("too many data parts, it should be no more than 2 parts") + panic(gerror.NewCode( + gcode.CodeInvalidParameter, + "too many data parts, it should be no more than 2 parts", + )) } return string(b) }