diff --git a/Any/convert.go b/Any/convert.go new file mode 100644 index 0000000..236ffba --- /dev/null +++ b/Any/convert.go @@ -0,0 +1,220 @@ +package Any + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "fmt" + "math" + "reflect" + "regexp" + "strconv" +) + +// Bytes convert any to bytes +func Bytes(value any) ([]byte, error) { + v := reflect.ValueOf(value) + + switch value.(type) { + case int, int8, int16, int32, int64: + number := v.Int() + buf := bytes.NewBuffer([]byte{}) + buf.Reset() + err := binary.Write(buf, binary.BigEndian, number) + return buf.Bytes(), err + case uint, uint8, uint16, uint32, uint64: + number := v.Uint() + buf := bytes.NewBuffer([]byte{}) + buf.Reset() + err := binary.Write(buf, binary.BigEndian, number) + return buf.Bytes(), err + case float32: + number := float32(v.Float()) + bits := math.Float32bits(number) + bytes := make([]byte, 4) + binary.BigEndian.PutUint32(bytes, bits) + return bytes, nil + case float64: + number := v.Float() + bits := math.Float64bits(number) + bytes := make([]byte, 8) + binary.BigEndian.PutUint64(bytes, bits) + return bytes, nil + case bool: + return strconv.AppendBool([]byte{}, v.Bool()), nil + case string: + return []byte(v.String()), nil + case []byte: + return v.Bytes(), nil + default: + newValue, err := json.Marshal(value) + return newValue, err + } +} + +// String convert value to string +func String(value any) string { + result := "" + if value == nil { + return result + } + + v := reflect.ValueOf(value) + + switch value.(type) { + case float32, float64: + result = strconv.FormatFloat(v.Float(), 'f', -1, 64) + return result + case int, int8, int16, int32, int64: + result = strconv.FormatInt(v.Int(), 10) + return result + case uint, uint8, uint16, uint32, uint64: + result = strconv.FormatUint(v.Uint(), 10) + return result + case string: + result = v.String() + return result + case []byte: + result = string(v.Bytes()) + return result + default: + newValue, _ := json.Marshal(value) + result = string(newValue) + return result + } +} + +// Float convert value to a float64, if input is not a float return 0.0 and error +func Float(value any) (float64, error) { + v := reflect.ValueOf(value) + + result := 0.0 + err := fmt.Errorf("ToInt: unvalid interface type %T", value) + switch value.(type) { + case int, int8, int16, int32, int64: + result = float64(v.Int()) + return result, nil + case uint, uint8, uint16, uint32, uint64: + result = float64(v.Uint()) + return result, nil + case float32, float64: + result = v.Float() + return result, nil + case string: + result, err = strconv.ParseFloat(v.String(), 64) + if err != nil { + result = 0.0 + } + return result, err + default: + return result, err + } +} + +// Int convert value to a int64, if input is not a numeric format return 0 and error +func Int(value any) (int64, error) { + v := reflect.ValueOf(value) + + var result int64 + err := fmt.Errorf("ToInt: invalid interface type %T", value) + switch value.(type) { + case int, int8, int16, int32, int64: + result = v.Int() + return result, nil + case uint, uint8, uint16, uint32, uint64: + result = int64(v.Uint()) + return result, nil + case float32, float64: + result = int64(v.Float()) + return result, nil + case string: + result, err = strconv.ParseInt(v.String(), 0, 64) + if err != nil { + result = 0 + } + return result, err + default: + return result, err + } +} + +// Pointer returns a pointer to this value +func Pointer[T any](value T) *T { + return &value +} + +// Map convert a slice or an array of structs to a map based on iteratee function +func Map[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V { + result := make(map[K]V, len(array)) + for _, item := range array { + k, v := iteratee(item) + result[k] = v + } + + return result +} + +// StructToMap convert struct to map, only convert exported struct field +// map key is specified same as struct field tag `json` value +func StructToMap(value any) (map[string]any, error) { + v := reflect.ValueOf(value) + t := reflect.TypeOf(value) + + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + if t.Kind() != reflect.Struct { + return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value) + } + + result := make(map[string]any) + + fieldNum := t.NumField() + pattern := `^[A-Z]` + regex := regexp.MustCompile(pattern) + for i := 0; i < fieldNum; i++ { + name := t.Field(i).Name + tag := t.Field(i).Tag.Get("json") + if regex.MatchString(name) && tag != "" { + //result[name] = v.Field(i).Interface() + result[tag] = v.Field(i).Interface() + } + } + + return result, nil +} + +// MapToSlice convert a map to a slice based on iteratee function +func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T { + result := make([]T, 0, len(aMap)) + + for k, v := range aMap { + result = append(result, iteratee(k, v)) + } + + return result +} + +// Json convert value to a valid json string +func Json(value any) (string, error) { + result, err := json.Marshal(value) + if err != nil { + return "", err + } + + return string(result), nil +} + +// Channel convert a array of elements to a read-only channels +func Channel[T any](array []T) <-chan T { + ch := make(chan T) + + go func() { + for _, item := range array { + ch <- item + } + close(ch) + }() + + return ch +} diff --git a/Any/convert_test.go b/Any/convert_test.go new file mode 100644 index 0000000..034c9ba --- /dev/null +++ b/Any/convert_test.go @@ -0,0 +1,86 @@ +package Any + +import ( + "fmt" + "strconv" + "testing" +) + +func TestString(t *testing.T) { + fmt.Println(String("hello world!")) + fmt.Println(String(123)) + fmt.Println(String(123.02)) + bs := []byte("hello world!") + fmt.Println(String(bs)) +} +func TestChannel(t *testing.T) { + var arr1 = []int{1, 2, 3, 4, 5} + ch := Channel(arr1) + fmt.Println(ch) + +} +func TestBytes(t *testing.T) { + fmt.Println(Bytes("hello world!")) + fmt.Println(String("hello world!")) +} +func TestJson(t *testing.T) { + fmt.Println(Json("hello world!")) + fmt.Println(Json(123)) + fmt.Println(Json(123.02)) + bs := []byte("hello world!") + fmt.Println(Json(bs)) +} +func TestFloat(t *testing.T) { + fmt.Println(Float(123)) + fmt.Println(Float(123.02)) + fmt.Println(Float("123.02")) + fmt.Println(Float("123.02f")) +} + +func TestInt(t *testing.T) { + fmt.Println(Int(123)) + fmt.Println(Int("123.005")) + fmt.Println(Int("123f")) +} +func TestPointer(t *testing.T) { + var a = 123 + pa := Pointer(a) + fmt.Println(a) + fmt.Println(pa) + fmt.Println(*pa) +} +func TestMap(t *testing.T) { + type Message struct { + name string + code int + } + messages := []Message{ + {name: "Hello", code: 100}, + {name: "Hi", code: 101}, + } + result := Map(messages, func(msg Message) (int, string) { + return msg.code, msg.name + }) + fmt.Println(result) + +} + +func TestStructToMap(t *testing.T) { + type People struct { + Name string `json:"name"` + age int + } + p := People{ + "test", + 100, + } + result, _ := StructToMap(p) + fmt.Println(result) +} +func TestMapToSlice(t *testing.T) { + aMap := map[string]int{"a": 1, "b": 2, "c": 3} + result := MapToSlice(aMap, func(key string, value int) string { + return key + ":" + strconv.Itoa(value) + }) + fmt.Println(result) +} diff --git a/convert/color.go b/convert/color.go new file mode 100644 index 0000000..e2c41cc --- /dev/null +++ b/convert/color.go @@ -0,0 +1,36 @@ +package convert + +import ( + "strconv" + "strings" +) + +// ColorHexToRGB convert hex color to rgb color +func (c *Conv) ColorHexToRGB(colorHex string) (red, green, blue int) { + colorHex = strings.TrimPrefix(colorHex, "#") + color64, err := strconv.ParseInt(colorHex, 16, 32) + if err != nil { + return + } + color := int(color64) + return color >> 16, (color & 0x00FF00) >> 8, color & 0x0000FF +} + +// ColorRGBToHex convert rgb color to hex color +func (c *Conv) ColorRGBToHex(red, green, blue int) string { + r := strconv.FormatInt(int64(red), 16) + g := strconv.FormatInt(int64(green), 16) + b := strconv.FormatInt(int64(blue), 16) + + if len(r) == 1 { + r = "0" + r + } + if len(g) == 1 { + g = "0" + g + } + if len(b) == 1 { + b = "0" + b + } + + return "#" + r + g + b +} diff --git a/convert/color_test.go b/convert/color_test.go new file mode 100644 index 0000000..c56de32 --- /dev/null +++ b/convert/color_test.go @@ -0,0 +1,13 @@ +package convert + +import ( + "fmt" + "testing" +) + +func TestConv_ColorHexToRGB(t *testing.T) { + fmt.Println(conv.ColorHexToRGB("#ff0000")) +} +func TestConv_ColorRGBToHex(t *testing.T) { + fmt.Println(conv.ColorRGBToHex(255, 0, 0)) +} diff --git a/convert/str.go b/convert/str.go index e559b41..9c0617f 100644 --- a/convert/str.go +++ b/convert/str.go @@ -2,6 +2,11 @@ package convert import "strconv" +// StrToBool convert string to a boolean +func (c *Conv) StrToBool(str string) (bool, error) { + return strconv.ParseBool(str) +} + // StrToInt 字符串转int类型,当存在defaultNum时,出现异常会返回设置的默认值,若不出现异常正常返回 func (c *Conv) StrToInt(str string, defaultNum ...int) int { num, err := strconv.Atoi(str) @@ -74,3 +79,16 @@ func (c *Conv) StrToFloat64(strFloat string, defaultFloat ...float64) float64 { } return float } + +// StrToSlice convert string to char slice +func (c *Conv) StrToSlice(str string) []string { + sls := make([]string, 0) + if len(str) == 0 { + sls = append(sls, "") + } + for _, v := range str { + sls = append(sls, string(v)) + } + return sls + +} diff --git a/convert/str_test.go b/convert/str_test.go index 1e20365..9706e06 100644 --- a/convert/str_test.go +++ b/convert/str_test.go @@ -17,3 +17,20 @@ func TestConv_StrToInt64(t *testing.T) { fmt.Println(conv.StrToInt64("34ttt567", 789)) } + +func TestConv_StrToBool(t *testing.T) { + fmt.Println(conv.StrToBool("true")) + fmt.Println(conv.StrToBool("false")) + fmt.Println(conv.StrToBool("true1")) + fmt.Println(conv.StrToBool("false2")) + fmt.Println(conv.StrToBool("0")) + fmt.Println(conv.StrToBool("1")) + fmt.Println(conv.StrToBool("2")) + fmt.Println(conv.StrToBool("3")) + +} + +func TestConv_StrToSlice(t *testing.T) { + fmt.Println(conv.StrToSlice("1,2,3,4,5")) + fmt.Println(conv.StrToSlice("hello,world")) +} diff --git a/crypto/hmac.go b/crypto/hmac.go new file mode 100644 index 0000000..b5da352 --- /dev/null +++ b/crypto/hmac.go @@ -0,0 +1,38 @@ +package crypto + +import ( + "crypto/hmac" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" +) + +// Md5Hmac return the hmac hash of string use md5 +func (c *Crypto) Md5Hmac(data, key string) string { + h := hmac.New(md5.New, []byte(key)) + h.Write([]byte(data)) + return hex.EncodeToString(h.Sum([]byte(""))) +} + +// Sha1Hmac return the hmac hash of string use sha1 +func (c *Crypto) Sha1Hmac(data, key string) string { + h := hmac.New(sha1.New, []byte(key)) + h.Write([]byte(data)) + return hex.EncodeToString(h.Sum([]byte(""))) +} + +// Sha256Hmac return the hmac hash of string use sha256 +func (c *Crypto) Sha256Hmac(data, key string) string { + h := hmac.New(sha256.New, []byte(key)) + h.Write([]byte(data)) + return hex.EncodeToString(h.Sum([]byte(""))) +} + +// Sha512Hmac return the hmac hash of string use sha512 +func (c *Crypto) Sha512Hmac(data, key string) string { + h := hmac.New(sha512.New, []byte(key)) + h.Write([]byte(data)) + return hex.EncodeToString(h.Sum([]byte(""))) +} diff --git a/crypto/hmac_test.go b/crypto/hmac_test.go new file mode 100644 index 0000000..07a6560 --- /dev/null +++ b/crypto/hmac_test.go @@ -0,0 +1,25 @@ +package crypto + +import ( + "fmt" + "testing" +) + +func TestCrypto_Md5Hmac(t *testing.T) { + fmt.Println(cryptoTool.Md5Hmac("hello world!", "123456")) + //0869302654295f1e6100539678192559 + fmt.Println(cryptoTool.Md5String("hello world!")) + //fc3ff98e8c6a0d3087d515c0473f8677 + fmt.Println(cryptoTool.Md5Hmac("hello world!", "")) + //3ce504dbfc6f5834fc52371727877f85 + +} + +func TestCrypto_ShaHmac(t *testing.T) { + fmt.Println(cryptoTool.Sha1Hmac("hello world!", "123456")) + //397d14b5c064f1f3a19c2e8d1f5108d797a47a3c + fmt.Println(cryptoTool.Sha256Hmac("hello world!", "123456")) + //03c6198ea823af32c338b1524d1653ccc065c06af916495a178208189555d428 + fmt.Println(cryptoTool.Sha512Hmac("hello world!", "123456")) + //8a432b00e63bbca7fe42d75d2517724af89f0d5404b42b828adbbcb87b1916e73c3a4186adab399ba636aee431ee35a238e75e87f29583189ca1502d3da9885e +} diff --git a/crypto/md5.go b/crypto/md5.go index 8071483..6132b86 100644 --- a/crypto/md5.go +++ b/crypto/md5.go @@ -2,7 +2,6 @@ package crypto import ( "bufio" - "crypto/hmac" "crypto/md5" "encoding/hex" "fmt" @@ -22,8 +21,11 @@ func (c *Crypto) Md5Encode(data string) string { h.Write([]byte(data)) return hex.EncodeToString(h.Sum(nil)) } +func (c *Crypto) Md5String(data string) string { + return c.Md5Encode(data) +} -// Md5File return the md5 value of file +// Md5EncodeFile return the md5 value of file func (c *Crypto) Md5EncodeFile(filename string) (string, error) { if fileInfo, err := os.Stat(filename); err != nil { return "", err @@ -54,10 +56,6 @@ func (c *Crypto) Md5EncodeFile(filename string) (string, error) { checksum := fmt.Sprintf("%x", hash.Sum(nil)) return checksum, nil } - -// Md5Hmac return the hmac hash of string use md5 -func (c *Crypto) Md5Hmac(data, key string) string { - h := hmac.New(md5.New, []byte(key)) - h.Write([]byte(data)) - return hex.EncodeToString(h.Sum([]byte(""))) +func (c *Crypto) Md5File(filename string) (string, error) { + return c.Md5EncodeFile(filename) } diff --git a/crypto/md5_test.go b/crypto/md5_test.go index 234bf3f..782900b 100644 --- a/crypto/md5_test.go +++ b/crypto/md5_test.go @@ -15,13 +15,13 @@ func TestMd5(tt *testing.T) { } +func TestCrypto_Md5String(t *testing.T) { + fmt.Println(cryptoTool.Md5String("hello world!")) + //fc3ff98e8c6a0d3087d515c0473f8677 +} + func TestCrypto_Md5EncodeFile(t *testing.T) { filePath := "./md5.go" fmt.Println(cryptoTool.Md5EncodeFile(filePath)) //fea07bd54d5c1841a682b408fbbb0cf8 } - -func TestCrypto_Md5Hmac(t *testing.T) { - fmt.Println(cryptoTool.Md5Hmac("hello world!", "123456")) - //0869302654295f1e6100539678192559 -} diff --git a/crypto/sha.go b/crypto/sha.go index 01614a6..01ee598 100644 --- a/crypto/sha.go +++ b/crypto/sha.go @@ -1,7 +1,6 @@ package crypto import ( - "crypto/hmac" "crypto/sha1" "crypto/sha256" "crypto/sha512" @@ -29,24 +28,3 @@ func (c *Crypto) Sha512Encode(data string) string { sha512.Write([]byte(data)) return hex.EncodeToString(sha512.Sum([]byte(""))) } - -// Sha1Hmac return the hmac hash of string use sha1 -func (c *Crypto) Sha1Hmac(data, key string) string { - h := hmac.New(sha1.New, []byte(key)) - h.Write([]byte(data)) - return hex.EncodeToString(h.Sum([]byte(""))) -} - -// Sha256Hmac return the hmac hash of string use sha256 -func (c *Crypto) Sha256Hmac(data, key string) string { - h := hmac.New(sha256.New, []byte(key)) - h.Write([]byte(data)) - return hex.EncodeToString(h.Sum([]byte(""))) -} - -// Sha512Hmac return the hmac hash of string use sha512 -func (c *Crypto) Sha512Hmac(data, key string) string { - h := hmac.New(sha512.New, []byte(key)) - h.Write([]byte(data)) - return hex.EncodeToString(h.Sum([]byte(""))) -} diff --git a/crypto/sha_test.go b/crypto/sha_test.go index 53647d2..2ac2c7f 100644 --- a/crypto/sha_test.go +++ b/crypto/sha_test.go @@ -13,12 +13,3 @@ func TestShaEncode(t *testing.T) { fmt.Println(cryptoTool.Sha512Encode("hello world!")) //db9b1cd3262dee37756a09b9064973589847caa8e53d31a9d142ea2701b1b28abd97838bb9a27068ba305dc8d04a45a1fcf079de54d607666996b3cc54f6b67c } - -func TestCrypto_ShaHmac(t *testing.T) { - fmt.Println(cryptoTool.Sha1Hmac("hello world!", "123456")) - //397d14b5c064f1f3a19c2e8d1f5108d797a47a3c - fmt.Println(cryptoTool.Sha256Hmac("hello world!", "123456")) - //03c6198ea823af32c338b1524d1653ccc065c06af916495a178208189555d428 - fmt.Println(cryptoTool.Sha512Hmac("hello world!", "123456")) - //8a432b00e63bbca7fe42d75d2517724af89f0d5404b42b828adbbcb87b1916e73c3a4186adab399ba636aee431ee35a238e75e87f29583189ca1502d3da9885e -}