From 81d13c2f1ae31526b764891a50e742ffabcee5c7 Mon Sep 17 00:00:00 2001 From: Cannian <59365095+cannian1@users.noreply.github.com> Date: Thu, 29 Feb 2024 19:22:32 +0800 Subject: [PATCH 1/2] feat(convertor): add ToBase64 related method (#194) --- convertor/convertor.go | 85 +++++++++ convertor/convertor_example_test.go | 180 +++++++++++++++++ convertor/convertor_test.go | 286 ++++++++++++++++++++++++++++ docs/api/packages/convertor.md | 273 ++++++++++++++++++++++++++ docs/en/api/packages/convertor.md | 275 +++++++++++++++++++++++++- 5 files changed, 1098 insertions(+), 1 deletion(-) diff --git a/convertor/convertor.go b/convertor/convertor.go index d90479d..1dcca55 100644 --- a/convertor/convertor.go +++ b/convertor/convertor.go @@ -6,6 +6,7 @@ package convertor import ( "bytes" + "encoding/base64" "encoding/binary" "encoding/gob" "encoding/json" @@ -394,3 +395,87 @@ func GbkToUtf8(bs []byte) ([]byte, error) { b, err := io.ReadAll(r) return b, err } + +// ToStdBase64 convert data to standard base64 encoding. +func ToStdBase64(value any) string { + if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) { + return "" + } + switch value.(type) { + case []byte: + return base64.StdEncoding.EncodeToString(value.([]byte)) + case string: + return base64.StdEncoding.EncodeToString([]byte(value.(string))) + case error: + return base64.StdEncoding.EncodeToString([]byte(value.(error).Error())) + default: + marshal, err := json.Marshal(value) + if err != nil { + return "" + } + return base64.StdEncoding.EncodeToString(marshal) + } +} + +// ToUrlBase64 convert data to URL base64 encoding. +func ToUrlBase64(value any) string { + if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) { + return "" + } + switch value.(type) { + case []byte: + return base64.URLEncoding.EncodeToString(value.([]byte)) + case string: + return base64.URLEncoding.EncodeToString([]byte(value.(string))) + case error: + return base64.URLEncoding.EncodeToString([]byte(value.(error).Error())) + default: + marshal, err := json.Marshal(value) + if err != nil { + return "" + } + return base64.URLEncoding.EncodeToString(marshal) + } +} + +// ToRawStdBase64 convert data to raw standard base64 encoding. +func ToRawStdBase64(value any) string { + if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) { + return "" + } + switch value.(type) { + case []byte: + return base64.RawStdEncoding.EncodeToString(value.([]byte)) + case string: + return base64.RawStdEncoding.EncodeToString([]byte(value.(string))) + case error: + return base64.RawStdEncoding.EncodeToString([]byte(value.(error).Error())) + default: + marshal, err := json.Marshal(value) + if err != nil { + return "" + } + return base64.RawStdEncoding.EncodeToString(marshal) + } +} + +// ToRawUrlBase64 convert data to raw URL base64 encoding. +func ToRawUrlBase64(value any) string { + if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) { + return "" + } + switch value.(type) { + case []byte: + return base64.RawURLEncoding.EncodeToString(value.([]byte)) + case string: + return base64.RawURLEncoding.EncodeToString([]byte(value.(string))) + case error: + return base64.RawURLEncoding.EncodeToString([]byte(value.(error).Error())) + default: + marshal, err := json.Marshal(value) + if err != nil { + return "" + } + return base64.RawURLEncoding.EncodeToString(marshal) + } +} diff --git a/convertor/convertor_example_test.go b/convertor/convertor_example_test.go index 297fe47..3ed7e3c 100644 --- a/convertor/convertor_example_test.go +++ b/convertor/convertor_example_test.go @@ -1,6 +1,7 @@ package convertor import ( + "errors" "fmt" "reflect" "strconv" @@ -391,3 +392,182 @@ func ExampleGbkToUtf8() { // true // hello } + +func ExampleToStdBase64() { + // if you want to see the result, please use 'base64.StdEncoding.DecodeString()' to decode the result + + afterEncode := ToStdBase64(nil) + fmt.Println(afterEncode) + + stringVal := "hello" + afterEncode = ToStdBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = ToStdBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = ToStdBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = ToStdBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = ToStdBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = ToStdBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = ToStdBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // + // aGVsbG8= + // aGVsbG8= + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ== + // MTIzLjQ1Ng== + // dHJ1ZQ== + // ZXJy +} + +func ExampleToUrlBase64() { + // if you want to see the result, please use 'base64.URLEncoding.DecodeString()' to decode the result + + stringVal := "hello" + afterEncode := ToUrlBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = ToUrlBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = ToUrlBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = ToUrlBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = ToUrlBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = ToUrlBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = ToUrlBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // aGVsbG8= + // aGVsbG8= + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ== + // MTIzLjQ1Ng== + // dHJ1ZQ== + // ZXJy +} + +func ExampleToRawStdBase64() { + // if you want to see the result, please use 'base64.RawStdEncoding.DecodeString()' to decode the result + stringVal := "hello" + afterEncode := ToRawStdBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = ToRawStdBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = ToRawStdBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = ToRawStdBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = ToRawStdBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = ToRawStdBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = ToRawStdBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // aGVsbG8 + // aGVsbG8 + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ + // MTIzLjQ1Ng + // dHJ1ZQ + // ZXJy +} + +func ExampleToRawUrlBase64() { + // if you want to see the result, please use 'base64.RawURLEncoding.DecodeString()' to decode the result + + stringVal := "hello" + afterEncode := ToRawUrlBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = ToRawUrlBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = ToRawUrlBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = ToRawUrlBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = ToRawUrlBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = ToRawUrlBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = ToRawUrlBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // aGVsbG8 + // aGVsbG8 + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ + // MTIzLjQ1Ng + // dHJ1ZQ + // ZXJy +} diff --git a/convertor/convertor_test.go b/convertor/convertor_test.go index 1b1c390..7587a1f 100644 --- a/convertor/convertor_test.go +++ b/convertor/convertor_test.go @@ -1,11 +1,15 @@ package convertor import ( + "encoding/base64" + "errors" "fmt" + "io" "reflect" "strconv" "testing" "unicode/utf8" + "unsafe" "github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/slice" @@ -461,3 +465,285 @@ func TestGbkToUtf8(t *testing.T) { assert.Equal(true, utf8.Valid(utf8Data)) assert.Equal("hello", string(utf8Data)) } + +func decodeBase64(data []byte) ([]byte, error) { + buf := make([]byte, base64.StdEncoding.DecodedLen(len(data))) + n, err := base64.StdEncoding.Decode(buf, data) + return buf[:n], err +} + +func TestToStdBase64(t *testing.T) { + t.Parallel() + assert := internal.NewAssert(t, "TestToStdBase64") + + r1 := ToStdBase64("abc") + d1, _ := base64.StdEncoding.DecodeString(r1) + assert.Equal("abc", string(d1)) + + r2 := ToStdBase64([]byte("abc")) + d2, _ := base64.StdEncoding.DecodeString(r2) + assert.Equal("abc", string(d2)) + + r3 := ToStdBase64(123) + d3, _ := base64.StdEncoding.DecodeString(r3) + assert.Equal("123", string(d3)) + + r4 := ToStdBase64(11.11) + d4, _ := base64.StdEncoding.DecodeString(r4) + assert.Equal("11.11", string(d4)) + + r5 := ToStdBase64(map[string]any{"name": "duke", "quantity": 1}) + d5, _ := base64.StdEncoding.DecodeString(r5) + assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5)) + + r6 := ToStdBase64([]int64{7, 5, 9, 4, 23}) + d6, _ := base64.StdEncoding.DecodeString(r6) + assert.Equal("[7,5,9,4,23]", string(d6)) + + r7 := ToStdBase64([]string{"7", "5", "9", "4", "23"}) + d7, _ := base64.StdEncoding.DecodeString(r7) + assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7)) + + r8 := ToStdBase64(nil) + d8, _ := base64.StdEncoding.DecodeString(r8) + assert.Equal("", string(d8)) + + ch := make(chan int, 3) + ch <- 1 + ch <- 2 + r9 := ToStdBase64(ch) + d9, _ := base64.StdEncoding.DecodeString(r9) + assert.Equal("", string(d9)) + + r10 := ToStdBase64(io.EOF) + d10, _ := base64.StdEncoding.DecodeString(r10) + assert.Equal("EOF", string(d10)) + + r11 := ToStdBase64(errors.New("test")) + d11, _ := base64.StdEncoding.DecodeString(r11) + assert.Equal("test", string(d11)) + + typedNil := (*int)(nil) + r12 := ToStdBase64(typedNil) + d12, _ := base64.StdEncoding.DecodeString(r12) + assert.Equal("", string(d12)) + + type nilInterface interface { + } + var nI nilInterface = nil + d13, _ := base64.StdEncoding.DecodeString(ToStdBase64(nI)) + assert.Equal("", string(d13)) + + var p unsafe.Pointer + d14, _ := base64.StdEncoding.DecodeString(ToStdBase64(p)) + assert.Equal("", string(d14)) +} + +func TestToUrlBase64(t *testing.T) { + t.Parallel() + assert := internal.NewAssert(t, "TestToUrlBase64") + + r1 := ToUrlBase64("abc") + d1, _ := base64.URLEncoding.DecodeString(r1) + assert.Equal("abc", string(d1)) + + r2 := ToUrlBase64([]byte("abc")) + d2, _ := base64.URLEncoding.DecodeString(r2) + assert.Equal("abc", string(d2)) + + r3 := ToUrlBase64(123) + d3, _ := base64.URLEncoding.DecodeString(r3) + assert.Equal("123", string(d3)) + + r4 := ToUrlBase64(11.11) + d4, _ := base64.URLEncoding.DecodeString(r4) + assert.Equal("11.11", string(d4)) + + r5 := ToUrlBase64(map[string]any{"name": "duke", "quantity": 1}) + d5, _ := base64.URLEncoding.DecodeString(r5) + assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5)) + + r6 := ToUrlBase64([]int64{7, 5, 9, 4, 23}) + d6, _ := base64.URLEncoding.DecodeString(r6) + assert.Equal("[7,5,9,4,23]", string(d6)) + + r7 := ToUrlBase64([]string{"7", "5", "9", "4", "23"}) + d7, _ := base64.URLEncoding.DecodeString(r7) + assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7)) + + r8 := ToUrlBase64(nil) + d8, _ := base64.URLEncoding.DecodeString(r8) + assert.Equal("", string(d8)) + + ch := make(chan int, 3) + ch <- 1 + ch <- 2 + r9 := ToUrlBase64(ch) + d9, _ := base64.URLEncoding.DecodeString(r9) + assert.Equal("", string(d9)) + + r10 := ToUrlBase64(io.EOF) + d10, _ := base64.URLEncoding.DecodeString(r10) + assert.Equal("EOF", string(d10)) + + r11 := ToUrlBase64(errors.New("test")) + d11, _ := base64.URLEncoding.DecodeString(r11) + assert.Equal("test", string(d11)) + + typedNil := (*int)(nil) + r12 := ToUrlBase64(typedNil) + d12, _ := base64.URLEncoding.DecodeString(r12) + assert.Equal("", string(d12)) + + type nilInterface interface { + } + var nI nilInterface = nil + d13, _ := base64.URLEncoding.DecodeString(ToUrlBase64(nI)) + assert.Equal("", string(d13)) + + var p unsafe.Pointer + d14, _ := base64.URLEncoding.DecodeString(ToUrlBase64(p)) + assert.Equal("", string(d14)) + + r15 := ToUrlBase64("4+3/4?=") + d15, _ := base64.URLEncoding.DecodeString(r15) + assert.Equal("4+3/4?=", string(d15)) +} + +func TestToRawStdBase64(t *testing.T) { + t.Parallel() + assert := internal.NewAssert(t, "TestToRawStdBase64") + + r1 := ToRawStdBase64("abc") + d1, _ := base64.RawStdEncoding.DecodeString(r1) + assert.Equal("abc", string(d1)) + + r2 := ToRawStdBase64([]byte("abc")) + d2, _ := base64.RawStdEncoding.DecodeString(r2) + assert.Equal("abc", string(d2)) + + r3 := ToRawStdBase64(123) + d3, _ := base64.RawStdEncoding.DecodeString(r3) + assert.Equal("123", string(d3)) + + r4 := ToRawStdBase64(11.11) + d4, _ := base64.RawStdEncoding.DecodeString(r4) + assert.Equal("11.11", string(d4)) + + r5 := ToRawStdBase64(map[string]any{"name": "duke", "quantity": 1}) + d5, _ := base64.RawStdEncoding.DecodeString(r5) + assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5)) + + r6 := ToRawStdBase64([]int64{7, 5, 9, 4, 23}) + d6, _ := base64.RawStdEncoding.DecodeString(r6) + assert.Equal("[7,5,9,4,23]", string(d6)) + + r7 := ToRawStdBase64([]string{"7", "5", "9", "4", "23"}) + d7, _ := base64.RawStdEncoding.DecodeString(r7) + assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7)) + + r8 := ToRawStdBase64(nil) + d8, _ := base64.RawStdEncoding.DecodeString(r8) + assert.Equal("", string(d8)) + + ch := make(chan int, 3) + ch <- 1 + ch <- 2 + r9 := ToRawStdBase64(ch) + d9, _ := base64.RawStdEncoding.DecodeString(r9) + assert.Equal("", string(d9)) + + r10 := ToRawStdBase64(io.EOF) + d10, _ := base64.RawStdEncoding.DecodeString(r10) + assert.Equal("EOF", string(d10)) + + r11 := ToRawStdBase64(errors.New("test")) + d11, _ := base64.RawStdEncoding.DecodeString(r11) + assert.Equal("test", string(d11)) + + typedNil := (*int)(nil) + r12 := ToRawStdBase64(typedNil) + d12, _ := base64.RawStdEncoding.DecodeString(r12) + assert.Equal("", string(d12)) + + type nilInterface interface { + } + var nI nilInterface = nil + d13, _ := base64.RawStdEncoding.DecodeString(ToRawStdBase64(nI)) + assert.Equal("", string(d13)) + + var p unsafe.Pointer + d14, _ := base64.RawStdEncoding.DecodeString(ToRawStdBase64(p)) + assert.Equal("", string(d14)) +} + +func TestToRawUrlBase64(t *testing.T) { + t.Parallel() + assert := internal.NewAssert(t, "TestToRawUrlBase64") + + r1 := ToRawUrlBase64("abc") + d1, _ := base64.RawURLEncoding.DecodeString(r1) + assert.Equal("abc", string(d1)) + + r2 := ToRawUrlBase64([]byte("abc")) + d2, _ := base64.RawURLEncoding.DecodeString(r2) + assert.Equal("abc", string(d2)) + + r3 := ToRawUrlBase64(123) + d3, _ := base64.RawURLEncoding.DecodeString(r3) + assert.Equal("123", string(d3)) + + r4 := ToRawUrlBase64(11.11) + d4, _ := base64.RawURLEncoding.DecodeString(r4) + assert.Equal("11.11", string(d4)) + + r5 := ToRawUrlBase64(map[string]any{"name": "duke", "quantity": 1}) + d5, _ := base64.RawURLEncoding.DecodeString(r5) + assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5)) + + r6 := ToRawUrlBase64([]int64{7, 5, 9, 4, 23}) + d6, _ := base64.RawURLEncoding.DecodeString(r6) + assert.Equal("[7,5,9,4,23]", string(d6)) + + r7 := ToRawUrlBase64([]string{"7", "5", "9", "4", "23"}) + d7, _ := base64.RawURLEncoding.DecodeString(r7) + assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7)) + + r8 := ToRawUrlBase64(nil) + d8, _ := base64.RawURLEncoding.DecodeString(r8) + assert.Equal("", string(d8)) + + ch := make(chan int, 3) + ch <- 1 + ch <- 2 + r9 := ToRawUrlBase64(ch) + d9, _ := base64.RawURLEncoding.DecodeString(r9) + assert.Equal("", string(d9)) + + r10 := ToRawUrlBase64(io.EOF) + d10, _ := base64.RawURLEncoding.DecodeString(r10) + assert.Equal("EOF", string(d10)) + + r11 := ToRawUrlBase64(errors.New("test")) + d11, _ := base64.RawURLEncoding.DecodeString(r11) + assert.Equal("test", string(d11)) + + typedNil := (*int)(nil) + r12 := ToRawUrlBase64(typedNil) + d12, _ := base64.RawURLEncoding.DecodeString(r12) + assert.Equal("", string(d12)) + + type nilInterface interface { + } + var nI nilInterface = nil + d13, _ := base64.RawURLEncoding.DecodeString(ToRawUrlBase64(nI)) + assert.Equal("", string(d13)) + + var p unsafe.Pointer + d14, _ := base64.RawURLEncoding.DecodeString(ToRawUrlBase64(p)) + assert.Equal("", string(d14)) + + r15 := ToRawUrlBase64("4+3/4?=") + d15, _ := base64.RawURLEncoding.DecodeString(r15) + assert.Equal("4+3/4?=", string(d15)) +} diff --git a/docs/api/packages/convertor.md b/docs/api/packages/convertor.md index 6a3e84d..71642e8 100644 --- a/docs/api/packages/convertor.md +++ b/docs/api/packages/convertor.md @@ -43,6 +43,10 @@ import ( - [ToInterface](#ToInterface) - [Utf8ToGbk](#Utf8ToGbk) - [GbkToUtf8](#GbkToUtf8) +- [ToStdBase64](#ToStdBase64) +- [ToUrlBase64](#ToUrlBase64) +- [ToRawStdBase64](#ToRawStdBase64) +- [ToRawUrlBase64](#ToRawUrlBase64)
@@ -876,3 +880,272 @@ func main() { // hello } ``` + +### ToStdBase64 + +

值转换为 StdBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串

+ +函数签名: + +```go +func ToStdBase64(value any) string +``` + +示例: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/convertor" +) + +func main() { + afterEncode := convertor.ToStdBase64(nil) + fmt.Println(afterEncode) + + afterEncode = convertor.ToStdBase64("") + fmt.Println(afterEncode) + + stringVal := "hello" + afterEncode = convertor.ToStdBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = convertor.ToStdBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = convertor.ToStdBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = convertor.ToStdBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = convertor.ToStdBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = convertor.ToStdBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = convertor.ToStdBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // + // + // aGVsbG8= + // aGVsbG8= + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ== + // MTIzLjQ1Ng== + // dHJ1ZQ== + // ZXJy +} + +``` + +### ToUrlBase64 + +

值转换为 ToUrlBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串

+ +函数签名: + +```go +func ToUrlBase64(value any) string +``` + +示例: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/convertor" +) + +func main() { + afterEncode := convertor.ToUrlBase64(nil) + fmt.Println(afterEncode) + + + stringVal := "hello" + afterEncode = convertor.ToUrlBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = convertor.ToUrlBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = convertor.ToUrlBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = convertor.ToUrlBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = convertor.ToUrlBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = convertor.ToUrlBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = convertor.ToUrlBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // + // aGVsbG8= + // aGVsbG8= + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ== + // MTIzLjQ1Ng== + // dHJ1ZQ== + // ZXJy +} + +``` + +### ToRawStdBase64 + +

值转换为 ToRawStdBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串

+ +函数签名: + +```go +func ToRawStdBase64(value any) string +``` + +示例: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/convertor" +) + +func main() { + + stringVal := "hello" + afterEncode = convertor.ToRawStdBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = convertor.ToRawStdBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = convertor.ToRawStdBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = convertor.ToRawStdBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = convertor.ToRawStdBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = convertor.ToRawStdBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = convertor.ToRawStdBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // aGVsbG8 + // aGVsbG8 + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ + // MTIzLjQ1Ng + // dHJ1ZQ + // ZXJy +} +``` + +### ToRawUrlBase64 + +

值转换为 ToRawUrlBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串

+ +函数签名: + +```go +func ToRawUrlBase64(value any) string +``` + +示例: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/convertor" +) + +func main() { + + stringVal := "hello" + afterEncode = convertor.ToRawUrlBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = convertor.ToRawUrlBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = convertor.ToRawUrlBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = convertor.ToRawUrlBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = convertor.ToRawUrlBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = convertor.ToRawStdBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = convertor.ToRawStdBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // aGVsbG8 + // aGVsbG8 + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ + // MTIzLjQ1Ng + // dHJ1ZQ + // ZXJy +} +``` \ No newline at end of file diff --git a/docs/en/api/packages/convertor.md b/docs/en/api/packages/convertor.md index 04bb628..c1ed5ea 100644 --- a/docs/en/api/packages/convertor.md +++ b/docs/en/api/packages/convertor.md @@ -43,6 +43,10 @@ import ( - [ToInterface](#ToInterface) - [Utf8ToGbk](#Utf8ToGbk) - [GbkToUtf8](#GbkToUtf8) +- [ToStdBase64](#ToStdBase64) +- [ToUrlBase64](#ToUrlBase64) +- [ToRawStdBase64](#ToRawStdBase64) +- [ToRawUrlBase64](#ToRawUrlBase64)
@@ -606,7 +610,7 @@ func main() { func DecodeByte(data []byte, target any) error ``` -Example:[Run](https://go.dev/play/p/zI6xsmuQRbn) +Example: ```go package main @@ -875,4 +879,273 @@ func main() { // true // hello } +``` + +### ToStdBase64 + +

Convert a value to a string encoded in standard Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON-formatted string.

+ +Signature: + +```go +func ToStdBase64(value any) string +``` + +Example: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/convertor" +) + +func main() { + afterEncode := convertor.ToStdBase64(nil) + fmt.Println(afterEncode) + + afterEncode = convertor.ToStdBase64("") + fmt.Println(afterEncode) + + stringVal := "hello" + afterEncode = convertor.ToStdBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = convertor.ToStdBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = convertor.ToStdBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = convertor.ToStdBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = convertor.ToStdBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = convertor.ToStdBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = convertor.ToStdBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // + // + // aGVsbG8= + // aGVsbG8= + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ== + // MTIzLjQ1Ng== + // dHJ1ZQ== + // ZXJy +} + +``` + +### ToUrlBase64 + +

Convert a value to a string encoded in Url Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON-formatted string.

+ +Signature: + +```go +func ToUrlBase64(value any) string +``` + +Example: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/convertor" +) + +func main() { + afterEncode := convertor.ToUrlBase64(nil) + fmt.Println(afterEncode) + + + stringVal := "hello" + afterEncode = convertor.ToUrlBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = convertor.ToUrlBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = convertor.ToUrlBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = convertor.ToUrlBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = convertor.ToUrlBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = convertor.ToUrlBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = convertor.ToUrlBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // + // aGVsbG8= + // aGVsbG8= + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ== + // MTIzLjQ1Ng== + // dHJ1ZQ== + // ZXJy +} + +``` + +### ToRawStdBase64 + +

Convert a value to a string encoded in raw standard Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON-formatted string.

+ +Signature: + +```go +func ToRawStdBase64(value any) string +``` + +Example: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/convertor" +) + +func main() { + + stringVal := "hello" + afterEncode = convertor.ToRawStdBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = convertor.ToRawStdBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = convertor.ToRawStdBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = convertor.ToRawStdBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = convertor.ToRawStdBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = convertor.ToRawStdBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = convertor.ToRawStdBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // aGVsbG8 + // aGVsbG8 + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ + // MTIzLjQ1Ng + // dHJ1ZQ + // ZXJy +} +``` + +### ToRawUrlBase64 + +

Convert a value to a string encoded in raw url Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON-formatted string.

+ +Signature: + +```go +func ToRawUrlBase64(value any) string +``` + +Example: + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/convertor" +) + +func main() { + + stringVal := "hello" + afterEncode = convertor.ToRawUrlBase64(stringVal) + fmt.Println(afterEncode) + + byteSliceVal := []byte("hello") + afterEncode = convertor.ToRawUrlBase64(byteSliceVal) + fmt.Println(afterEncode) + + intVal := 123 + afterEncode = convertor.ToRawUrlBase64(intVal) + fmt.Println(afterEncode) + + mapVal := map[string]any{"a": "hi", "b": 2, "c": struct { + A string + B int + }{"hello", 3}} + afterEncode = convertor.ToRawUrlBase64(mapVal) + fmt.Println(afterEncode) + + floatVal := 123.456 + afterEncode = convertor.ToRawUrlBase64(floatVal) + fmt.Println(afterEncode) + + boolVal := true + afterEncode = convertor.ToRawStdBase64(boolVal) + fmt.Println(afterEncode) + + errVal := errors.New("err") + afterEncode = convertor.ToRawStdBase64(errVal) + fmt.Println(afterEncode) + + // Output: + // aGVsbG8 + // aGVsbG8 + // MTIz + // eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ + // MTIzLjQ1Ng + // dHJ1ZQ + // ZXJy +} ``` \ No newline at end of file From c02c4f813bb3e3871f60b9df35a9287fb74bb501 Mon Sep 17 00:00:00 2001 From: Cannian <59365095+cannian1@users.noreply.github.com> Date: Fri, 1 Mar 2024 16:04:23 +0800 Subject: [PATCH 2/2] refactor(mathutil): round related method support generics (#195) --- docs/api/packages/mathutil.md | 6 +++--- docs/en/api/packages/mathutil.md | 6 +++--- mathutil/mathutil.go | 20 ++++++++++---------- mathutil/mathutil_test.go | 10 ++++++++-- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/docs/api/packages/mathutil.md b/docs/api/packages/mathutil.md index d065364..f4e67c0 100644 --- a/docs/api/packages/mathutil.md +++ b/docs/api/packages/mathutil.md @@ -392,7 +392,7 @@ func main() { 函数签名: ```go -func RoundToFloat(x float64, n int) float64 +func RoundToFloat[T constraints.Float | constraints.Integer](x T, n int) float64 ``` 示例:[运行](https://go.dev/play/p/ghyb528JRJL) @@ -428,7 +428,7 @@ func main() { 函数签名: ```go -func RoundToString(x float64, n int) string +func RoundToString[T constraints.Float | constraints.Integer](x T, n int) string ``` 示例:[运行](https://go.dev/play/p/kZwpBRAcllO) @@ -464,7 +464,7 @@ func main() { 函数签名: ```go -func TruncRound(x float64, n int) float64 +func TruncRound[T constraints.Float | constraints.Integer](x T, n int) T ``` 示例:[运行](https://go.dev/play/p/aumarSHIGzP) diff --git a/docs/en/api/packages/mathutil.md b/docs/en/api/packages/mathutil.md index 71146f0..af61ba3 100644 --- a/docs/en/api/packages/mathutil.md +++ b/docs/en/api/packages/mathutil.md @@ -392,7 +392,7 @@ func main() { Signature: ```go -func RoundToFloat(x float64, n int) float64 +func RoundToFloat[T constraints.Float | constraints.Integer](x T, n int) float64 ``` Example:[Run](https://go.dev/play/p/ghyb528JRJL) @@ -428,7 +428,7 @@ func main() { Signature: ```go -func RoundToString(x float64, n int) string +func RoundToString[T constraints.Float | constraints.Integer](x T, n int) string ``` Example:[Run](https://go.dev/play/p/kZwpBRAcllO) @@ -464,7 +464,7 @@ func main() { Signature: ```go -func TruncRound(x float64, n int) float64 +func TruncRound[T constraints.Float | constraints.Integer](x T, n int) T ``` Example:[Run](https://go.dev/play/p/aumarSHIGzP) diff --git a/mathutil/mathutil.go b/mathutil/mathutil.go index 280ca56..4248d99 100644 --- a/mathutil/mathutil.go +++ b/mathutil/mathutil.go @@ -68,26 +68,26 @@ func Percent(val, total float64, n int) float64 { // RoundToString round up to n decimal places. // Play: https://go.dev/play/p/kZwpBRAcllO -func RoundToString(x float64, n int) string { +func RoundToString[T constraints.Float | constraints.Integer](x T, n int) string { tmp := math.Pow(10.0, float64(n)) - x *= tmp - x = math.Round(x) - result := strconv.FormatFloat(x/tmp, 'f', n, 64) + x *= T(tmp) + r := math.Round(float64(x)) + result := strconv.FormatFloat(r/tmp, 'f', n, 64) return result } // RoundToFloat round up to n decimal places. // Play: https://go.dev/play/p/ghyb528JRJL -func RoundToFloat(x float64, n int) float64 { +func RoundToFloat[T constraints.Float | constraints.Integer](x T, n int) float64 { tmp := math.Pow(10.0, float64(n)) - x *= tmp - x = math.Round(x) - return x / tmp + x *= T(tmp) + r := math.Round(float64(x)) + return r / tmp } // TruncRound round off n decimal places. // Play: https://go.dev/play/p/aumarSHIGzP -func TruncRound(x float64, n int) float64 { +func TruncRound[T constraints.Float | constraints.Integer](x T, n int) T { floatStr := fmt.Sprintf("%."+strconv.Itoa(n+1)+"f", x) temp := strings.Split(floatStr, ".") var newFloat string @@ -97,7 +97,7 @@ func TruncRound(x float64, n int) float64 { newFloat = temp[0] + "." + temp[1][:n] } result, _ := strconv.ParseFloat(newFloat, 64) - return result + return T(result) } // Max return max value of numbers. diff --git a/mathutil/mathutil_test.go b/mathutil/mathutil_test.go index dbb9031..fb7cf99 100644 --- a/mathutil/mathutil_test.go +++ b/mathutil/mathutil_test.go @@ -72,6 +72,8 @@ func TestRoundToString(t *testing.T) { assert.Equal("0.12", RoundToString(0.124, 2)) assert.Equal("0.13", RoundToString(0.125, 2)) assert.Equal("0.125", RoundToString(0.125, 3)) + //assert.Equal("54.321", RoundToString(54.321, 3)) + //assert.Equal("17.000", RoundToString(17, 3)) } func TestTruncRound(t *testing.T) { @@ -79,8 +81,12 @@ func TestTruncRound(t *testing.T) { assert := internal.NewAssert(t, "TestTruncRound") - assert.Equal(float64(0), TruncRound(0, 0)) - assert.Equal(float64(0), TruncRound(0, 1)) + assert.Equal(float64(0), TruncRound(float64(0), 0)) + assert.Equal(float64(0), TruncRound(float64(0), 1)) + assert.Equal(float32(0), TruncRound(float32(0), 0)) + assert.Equal(float32(0), TruncRound(float32(0), 1)) + assert.Equal(0, TruncRound(0, 0)) + assert.Equal(uint64(0), TruncRound(uint64(0), 1)) assert.Equal(0.12, TruncRound(0.124, 2)) assert.Equal(0.12, TruncRound(0.125, 2)) assert.Equal(0.125, TruncRound(0.125, 3))