diff --git a/jsonUtil/README.md b/jsonUtil/README.md index af8da0c..c9a5841 100644 --- a/jsonUtil/README.md +++ b/jsonUtil/README.md @@ -1,20 +1,29 @@ # jsonUtil -根据结构体的字段类型和标签来自动选择将 JSON 值转换为相应的类型。 +## Introduce -支持的字段类型包括 string、int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、bool、float32 和 float64。 +
+English +
+JsonToStruct is a method that parses a JSON string into a struct. This method accepts two parameters:
+- jsonData: the JSON string to be parsed
+- result: a pointer to an instance of a struct used to store the parsed data
+The method uses reflection to parse the struct and extracts the corresponding values from the JSON based on the fields defined in the struct and their corresponding JSON tags. If a field in the struct is a nested struct, it recursively parses the nested struct and stores the result in the parent struct.
+This method can handle basic data types such as strings, integers, floating-point numbers, booleans, as well as nested structs and slices. If a value in the JSON string cannot be converted to the target type, the method will return an error.
+
+
-支持的标签有 "json"、"jsonb" 和 "mapstructure"。 -- "json" 和 "jsonb" 标签指示解析 JSON 时使用的键名。 -- "mapstructure" 标签指示字段名的映射关系。 +
+简体中文 +
+JsonToStruct 是一个将JSON字符串解析为结构体的方法。这个方法接受两个参数:
+- jsonData:待解析的JSON字符串
+- result:用于存储解析后数据的结构体实例的指针
+该方法使用了反射机制来解析结构体,并根据结构体中定义的字段和对应的json标签从JSON中提取对应的值。如果结构体的字段是一个嵌套的结构体,它将递归解析嵌套的结构体,并将结果存储在父结构体中。
+该方法可以处理基本数据类型,如字符串、整数、浮点数、布尔值以及嵌套的结构体和切片。如果JSON字符串中的值无法转换为目标类型,该方法将返回一个错误。
+
+
-如果 JSON 中的某些键在结构体中没有对应的字段,则它们将被忽略。 -如果 JSON 中的某些键的类型与结构体中的字段类型不匹配,则会引发解析错误。 - -参数 jsonData 是要解析的 JSON 字符串。 -参数 result 是指向要填充 JSON 值的结构体指针。 - -如果解析成功,则返回 nil。如果解析失败,则返回解析错误。 ## Install @@ -25,6 +34,70 @@ go get -u github.com/jefferyjob/go-easy-utils/jsonUtil ## Functions ```go -// JsonToStruct 将 JSON 字符串解析为指定的结构体指针 +// JsonToStruct Parses JSON into a specified structure pointer +// 将JSON解析为指定的结构体指针 func JsonToStruct(jsonData string, result interface{}) error +``` + +## Demo + +```go +// name uses two json tags +// age is defined as int, and the value of json is string +// is_use is defined as bool, the value of json is int +func TestDemo1(t *testing.T) { + jsonData := `{ + "name": "make", + "age": "22", + "is_use": "1" + }` + type People struct { + Name string `json:"name,omitempty"` + Age int `json:"age"` + IsUse bool `json:"is_use"` + } + var people People + if err := JsonToStruct(jsonData, &people); err != nil { + fmt.Println(err) + return + } + fmt.Printf("%+v \n", people) + // return + // {Name:make Age:22 IsUse:true} +} +``` + +```go +// Structure nesting and slice nesting processing +func TestJsonToStructDemo2(t *testing.T) { + type Address struct { + City string `json:"city"` + Country string `json:"country"` + } + type Person struct { + Name string `json:"name"` + Age int `json:"age"` + Address Address `json:"address"` + Interests []string `json:"interests"` + } + + jsonData2 := `{ + "name": "Bob", + "age": "25", + "address": { + "city": "Shanghai", + "country": "China" + }, + "interests": ["reading", "swimming"] + }` + + var person Person + err := JsonToStruct(jsonData2, &person) + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("%+v \n", person) + // {Name:Bob Age:25 Address:{City:Shanghai Country:China} Interests:[reading swimming]} +} ``` \ No newline at end of file diff --git a/jsonUtil/json_to_struct.go b/jsonUtil/json_to_struct.go index 4732f7f..5d33e69 100644 --- a/jsonUtil/json_to_struct.go +++ b/jsonUtil/json_to_struct.go @@ -2,13 +2,13 @@ package jsonUtil import ( "encoding/json" - "github.com/jefferyjob/go-easy-utils" + "log" "reflect" - "strconv" "strings" ) -// JsonToStruct 将 JSON 字符串解析为指定的结构体指针 +// JsonToStruct Parses JSON into a specified structure pointer +// 将JSON解析为指定的结构体指针 func JsonToStruct(jsonData string, result interface{}) error { var data map[string]interface{} err := json.Unmarshal([]byte(jsonData), &data) @@ -41,27 +41,30 @@ func JsonToStruct(jsonData string, result interface{}) error { switch fieldValue.Kind() { case reflect.String: - fieldValue.SetString(toString(value)) + fieldValue.SetString(toStringReflect(value)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - val, err := toInt64(value) + val, err := toInt64Reflect(value) if err != nil { + log.Printf("toInt64Reflect err:%s \n", err) return err } fieldValue.SetInt(val) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - val, err := toUint64(value) + val, err := toUint64Reflect(value) if err != nil { + log.Printf("toUint64Reflect err:%s \n", err) return err } fieldValue.SetUint(val) case reflect.Float32, reflect.Float64: - val, err := toFloat64(value) + val, err := toFloat64Reflect(value) if err != nil { + log.Printf("toFloat64Reflect err:%s \n", err) return err } fieldValue.SetFloat(val) case reflect.Bool: - val := toBool(value) + val := toBoolReflect(value) fieldValue.SetBool(val) case reflect.Struct: if subData, ok := value.(map[string]interface{}); ok { @@ -98,196 +101,15 @@ func JsonToStruct(jsonData string, result interface{}) error { // fieldValue.Set(reflect.ValueOf(value)) } } - return nil } +//func isJSON(jsonStr string) bool { +// var raw json.RawMessage +// return json.Unmarshal([]byte(jsonStr), &raw) == nil +//} + func convertToJSONString(data map[string]interface{}) string { jsonBytes, _ := json.Marshal(data) return string(jsonBytes) } - -func toBool(value interface{}) bool { - switch v := value.(type) { - case bool: - return v - case string: - return v != "" && v != "false" && v != "0" - case int, int8, int16, int32, int64: - return v != 0 - case uint, uint8, uint16, uint32, uint64, uintptr: - return v != 0 - case float32, float64: - return v != 0.0 - case complex64, complex128: - return v != 0+0i - case nil: - return false - default: - return false - } -} - -func toString(value interface{}) string { - if value == nil { - return "" - } - - switch v := value.(type) { - case string: - return v - case int: - return strconv.Itoa(v) - case int8: - return strconv.FormatInt(int64(v), 10) - case int16: - return strconv.FormatInt(int64(v), 10) - case int32: - return strconv.FormatInt(int64(v), 10) - case int64: - return strconv.FormatInt(v, 10) - case uint: - return strconv.FormatUint(uint64(v), 10) - case uint8: - return strconv.FormatUint(uint64(v), 10) - case uint16: - return strconv.FormatUint(uint64(v), 10) - case uint32: - return strconv.FormatUint(uint64(v), 10) - case uint64: - return strconv.FormatUint(v, 10) - case float32: - return strconv.FormatFloat(float64(v), 'f', -1, 32) - case float64: - return strconv.FormatFloat(v, 'f', -1, 64) - case bool: - return strconv.FormatBool(v) - default: - return "" - } -} - -func toInt64(value interface{}) (int64, error) { - if value == nil { - return 0, nil - } - - switch value.(type) { - case float32: - return int64(value.(float32)), nil - case float64: - return int64(value.(float64)), nil - case string: - intValue, err := strconv.ParseInt(value.(string), 10, 64) - if err != nil { - return 0, go_easy_utils.ErrSyntax - } - return intValue, nil - case int: - return int64(value.(int)), nil - case int8: - return int64(value.(int8)), nil - case int16: - return int64(value.(int16)), nil - case int32: - return int64(value.(int32)), nil - case int64: - return value.(int64), nil - case interface{}: - return 0, nil - default: - return 0, go_easy_utils.ErrType - } -} - -func toUint64(value interface{}) (uint64, error) { - if value == nil { - return 0, nil - } - - switch value.(type) { - case float32: - v := value.(float32) - if v < 0 { - return 0, nil - } - return uint64(v), nil - case float64: - v := value.(float64) - if v < 0 { - return 0, nil - } - return uint64(v), nil - case string: - intValue, err := strconv.ParseUint(value.(string), 10, 64) - if err != nil { - return 0, go_easy_utils.ErrSyntax - } - return intValue, nil - case uint: - return uint64(value.(uint)), nil - case uint8: - return uint64(value.(uint8)), nil - case uint16: - return uint64(value.(uint16)), nil - case uint32: - return uint64(value.(uint32)), nil - case uint64: - return value.(uint64), nil - case int: - v := value.(int) - if v < 0 { - return 0, nil - } - return uint64(v), nil - case int8: - v := value.(int8) - if v < 0 { - return 0, nil - } - return uint64(v), nil - case int16: - v := value.(int16) - if v < 0 { - return 0, nil - } - return uint64(v), nil - case int32: - v := value.(int32) - if v < 0 { - return 0, nil - } - return uint64(v), nil - case int64: - v := value.(int64) - if v < 0 { - return 0, nil - } - return uint64(v), nil - case interface{}: - return 0, nil - default: - return 0, go_easy_utils.ErrType - } -} - -func toFloat64(value interface{}) (float64, error) { - if value == nil { - return 0, nil - } - - switch value.(type) { - case float32: - return float64(value.(float32)), nil - case float64: - return value.(float64), nil - case string: - floatValue, err := strconv.ParseFloat(value.(string), 64) - if err != nil { - return 0, go_easy_utils.ErrSyntax - } - return floatValue, nil - default: - return 0, go_easy_utils.ErrType - } -} diff --git a/jsonUtil/json_to_struct_test.go b/jsonUtil/json_to_struct_test.go index e30237a..2e32b28 100644 --- a/jsonUtil/json_to_struct_test.go +++ b/jsonUtil/json_to_struct_test.go @@ -6,6 +6,77 @@ import ( "testing" ) +// name uses two json tags +// age is defined as int, and the value of json is string +// is_use is defined as bool, the value of json is int +func TestDemo1(t *testing.T) { + jsonData := `{ + "name": "make", + "age": "22", + "is_use": "1" + }` + type People struct { + Name string `json:"name,omitempty"` + Age int `json:"age"` + IsUse bool `json:"is_use"` + } + var people People + if err := JsonToStruct(jsonData, &people); err != nil { + fmt.Println(err) + return + } + fmt.Printf("%+v \n", people) + // return + // {Name:make Age:22 IsUse:true} +} + +// Structure nesting and slice nesting processing +func TestJsonToStructDemo2(t *testing.T) { + type Address struct { + City string `json:"city"` + Country string `json:"country"` + } + type Person struct { + Name string `json:"name"` + Age int `json:"age"` + Address Address `json:"address"` + Interests []string `json:"interests"` + } + + jsonData2 := `{ + "name": "Bob", + "age": "25", + "address": { + "city": "Shanghai", + "country": "China" + }, + "interests": ["reading", "swimming"] + }` + + var person Person + err := JsonToStruct(jsonData2, &person) + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("%+v \n", person) + // {Name:Bob Age:25 Address:{City:Shanghai Country:China} Interests:[reading swimming]} +} + +// 非法的json字符串 +func TestJsonToStructErrJson(t *testing.T) { + jsonData := `{"name":}` + type People struct { + Name string `json:"name"` + } + var people People + err := JsonToStruct(jsonData, &people) + if err == nil { + t.Errorf("err %s", err) + return + } +} + func TestJsonToStruct1(t *testing.T) { type Address struct { City string `json:"city"` @@ -108,38 +179,6 @@ func TestJsonToStruct2(t *testing.T) { } -func TestJsonToStruct3(t *testing.T) { - type Address struct { - City string `json:"city"` - Country string `json:"country"` - } - - type Person struct { - Name string `json:"name"` - Age int `json:"age"` - Address Address `json:"address"` - Interests []string `json:"interests"` - } - - jsonData2 := `{ - "name": "Bob", - "age": "25", - "address": { - "city": "Shanghai", - "country": "China" - }, - "interests": ["reading", "swimming"] - }` - - var person2 Person - err := JsonToStruct(jsonData2, &person2) - if err != nil { - log.Fatal(err) - } - - fmt.Printf("person2:%+v,, address:%+v \n", person2, person2.Address) -} - // 多层级json测试 func TestJsonToStruct4(t *testing.T) { type Address struct { @@ -242,7 +281,3 @@ func TestJsonToStruct7(t *testing.T) { fmt.Printf("%#v \n", student) } - -func TestToUint64(t *testing.T) { - fmt.Println(toUint64("")) -} diff --git a/jsonUtil/log.md b/jsonUtil/log.md new file mode 100644 index 0000000..6eb862b --- /dev/null +++ b/jsonUtil/log.md @@ -0,0 +1,42 @@ +// 检查解引用后的值是否为 nil + +```go +if reflect.ValueOf(i).Kind() == reflect.Ptr && reflect.ValueOf(i).IsNil() { + return 0, nil +} +``` + + + +```go +v := reflect.ValueOf(i) +for v.Kind() == reflect.Ptr { + if v.IsNil() { + return 0, nil + } + v = v.Elem() +} +``` + + +这两个写法都是使用反射判断指针是否为nil,但它们的实现方式略有不同。 + +第一种写法将值i转换为反射值,并检查其种类是否为指针(reflect.Ptr),然后检查其是否为nil(reflect.Value.IsNil())。如果是,则返回0和nil。 + +第二种写法首先获取值i的反射值v,并检查其种类是否为指针。如果是,则继续获取其指向的元素(reflect.Value.Elem()),并将其赋给v,以便进一步检查。这个过程一直重复,直到v不再是指针或者v指向的元素不是nil为止。 + +两种写法都可以检查指针是否为nil,但第二种写法允许进一步检查指针指向的元素是否为nil,因此更加灵活和精确。 + +```go + + +``` + + + +// 如果是指针类型 +//这段代码的作用是将value指向的值转换为非指针类型的值,具体来说,它会循环检查v是否为指针类型,如果是指针类型,则通过Elem方法获取其指向的值,直到v不再是指针类型为止。 +// +//在reflect包中,指针类型和其指向的值的类型是不同的。例如,一个指向int类型的指针,其类型是*int,而其指向的值的类型是int。因此,在使用reflect包时,我们需要注意区分指针类型和其指向的值的类型,否则可能会出现类型错误等问题。 +// +//因此,对于value为指针类型的情况,我们需要通过Elem方法获取其指向的值,然后再进行类型转换。而在使用Elem方法之前,我们需要先检查v是否为指针类型,因此使用循环语句进行判断。 diff --git a/jsonUtil/to_bool.go b/jsonUtil/to_bool.go new file mode 100644 index 0000000..0f5945f --- /dev/null +++ b/jsonUtil/to_bool.go @@ -0,0 +1,113 @@ +package jsonUtil + +import ( + "fmt" + "reflect" +) + +func toBool(i interface{}) bool { + if i == nil { + return false + } + + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return false + } + i = reflect.ValueOf(i).Elem().Interface() + } + + switch v := i.(type) { + case bool: + return v + case int: + return v != 0 + case int8: + return v != 0 + case int16: + return v != 0 + case int32: + return v != 0 + case int64: + return v != 0 + case uint: + return v != 0 + case uint8: + return v != 0 + case uint16: + return v != 0 + case uint32: + return v != 0 + case uint64: + return v != 0 + case uintptr: + return v != 0 + case float32: + return v != 0 + case float64: + return v != 0 + case complex64: + return v != 0 + case complex128: + return v != 0 + case string: + if v == "true" { + return true + } else if v == "false" { + return false + } + return v != "" + case fmt.Stringer: + return v.String() != "" + case interface{ IsNil() bool }: + return !v.IsNil() + default: + return false + } +} + +func toBoolReflect(i interface{}) bool { + if i == nil { + return false + } + + // 检查解引用后的值是否为 nil + if reflect.ValueOf(i).Kind() == reflect.Ptr && reflect.ValueOf(i).IsNil() { + return false + } + + v := reflect.ValueOf(i) + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return false + } + v = reflect.ValueOf(i).Elem() + } + + switch v.Kind() { + case reflect.Bool: + return v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() != 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() != 0 + case reflect.Float32, reflect.Float64: + return v.Float() != 0 + case reflect.Complex64, reflect.Complex128: + return v.Complex() != 0 + case reflect.String: + val := v.String() + if val == "true" { + return true + } else if val == "false" { + return false + } + return v.String() != "" + //case reflect.Ptr, reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Slice: + // return !v.IsNil() + default: + return false + } +} diff --git a/jsonUtil/to_bool_test.go b/jsonUtil/to_bool_test.go new file mode 100644 index 0000000..7092de0 --- /dev/null +++ b/jsonUtil/to_bool_test.go @@ -0,0 +1,57 @@ +package jsonUtil + +import "testing" + +func TestToBool(t *testing.T) { + var tests = []struct { + input interface{} + want bool + }{ + {true, true}, + {false, false}, + {int(-1), true}, + {int(1), true}, + {int(0), false}, + {int8(1), true}, + {int8(0), false}, + {int16(1), true}, + {int16(0), false}, + {int32(1), true}, + {int32(0), false}, + {int64(1), true}, + {int64(0), false}, + {uint(1), true}, + {uint(0), false}, + {uint8(1), true}, + {uint8(0), false}, + {uint16(1), true}, + {uint16(0), false}, + {uint32(1), true}, + {uint32(0), false}, + {uint64(1), true}, + {uint64(0), false}, + {float32(1.0), true}, + {float32(0.0), false}, + {float64(1.0), true}, + {float64(0.0), false}, + {"abc", true}, + {"true", true}, + {"false", false}, + {"", false}, + {nil, false}, + {complex64(1 + 1i), true}, + {complex64(0 + 0i), false}, + {complex128(1 + 1i), true}, + {complex128(0 + 0i), false}, + {(*int)(nil), false}, + } + for _, test := range tests { + if got := toBool(test.input); got != test.want { + t.Errorf("toBool(%v) = %v; want %v", test.input, got, test.want) + } + + if got := toBoolReflect(test.input); got != test.want { + t.Errorf("toBool(%v) = %v; want %v", test.input, got, test.want) + } + } +} diff --git a/jsonUtil/to_float.go b/jsonUtil/to_float.go new file mode 100644 index 0000000..60c1e17 --- /dev/null +++ b/jsonUtil/to_float.go @@ -0,0 +1,156 @@ +package jsonUtil + +import ( + "fmt" + "github.com/jefferyjob/go-easy-utils" + "reflect" + "strconv" +) + +func toFloat64(i interface{}) (float64, error) { + if i == nil { + return 0, nil + } + + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return 0, nil + } + i = reflect.ValueOf(i).Elem().Interface() + } + + switch v := i.(type) { + case float32: + return float64(v), nil + case float64: + return v, nil + case string: + floatValue, err := strconv.ParseFloat(v, 64) + if err != nil { + return 0, go_easy_utils.ErrSyntax + } + return floatValue, nil + case uint: + return float64(v), nil + case uint8: + return float64(v), nil + case uint16: + return float64(v), nil + case uint32: + return float64(v), nil + case uint64: + return float64(v), nil + case int: + return float64(v), nil + case int8: + return float64(v), nil + case int16: + return float64(v), nil + case int32: + return float64(v), nil + case int64: + return float64(v), nil + case complex64: + return float64(real(v)), nil + case complex128: + return real(v), nil + case bool: + if v { + return 1, nil + } else { + return 0, nil + } + //case *float32: + // return float64(*v), nil + //case *float64: + // return *v, nil + //case *string: + // floatValue, err := strconv.ParseFloat(*v, 64) + // if err != nil { + // return 0, go_easy_utils.ErrSyntax + // } + // return floatValue, nil + //case *uint: + // return float64(*v), nil + //case *uint8: + // return float64(*v), nil + //case *uint16: + // return float64(*v), nil + //case *uint32: + // return float64(*v), nil + //case *uint64: + // return float64(*v), nil + //case *int: + // return float64(*v), nil + //case *int8: + // return float64(*v), nil + //case *int16: + // return float64(*v), nil + //case *int32: + // return float64(*v), nil + //case *int64: + // return float64(*v), nil + //case *complex64: + // return float64(real(*v)), nil + //case *complex128: + // return real(*v), nil + //case *bool: + // if v != nil && *v { + // return 1, nil + // } else { + // return 0, nil + // } + default: + return 0, go_easy_utils.ErrType + } +} + +func toFloat64Reflect(i interface{}) (float64, error) { + if i == nil { + return 0, nil + } + + // 检查解引用后的值是否为 nil + if reflect.ValueOf(i).Kind() == reflect.Ptr && reflect.ValueOf(i).IsNil() { + return 0, nil + } + + v := reflect.ValueOf(i) + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return 0, nil + } + v = reflect.ValueOf(i).Elem() + } + + switch v.Kind() { + case reflect.Float32, reflect.Float64: + return v.Float(), nil + case reflect.String: + floatValue, err := strconv.ParseFloat(v.String(), 64) + if err != nil { + return 0, go_easy_utils.ErrSyntax + } + return floatValue, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + fmt.Println("怎么可以到这里呢") + return float64(v.Int()), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return float64(v.Uint()), nil + case reflect.Complex64, reflect.Complex128: + return real(v.Complex()), nil + case reflect.Bool: + if v.Bool() { + return 1, nil + } else { + return 0, nil + } + //case reflect.Ptr, reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Slice: + // return 0, nil + default: + return 0, go_easy_utils.ErrType + } + +} diff --git a/jsonUtil/to_float_test.go b/jsonUtil/to_float_test.go new file mode 100644 index 0000000..904af79 --- /dev/null +++ b/jsonUtil/to_float_test.go @@ -0,0 +1,279 @@ +package jsonUtil + +import ( + go_easy_utils "github.com/jefferyjob/go-easy-utils" + "reflect" + "testing" +) + +//func TestFloat(t *testing.T) { +// var data1 interface{} +// data1 = 123 +// fmt.Println(toFloat64Reflect(data1)) +// +// data2 := int16Ptr(80) +// fmt.Println(toFloat64Reflect(data2)) +// +// data3 := map[interface{}]interface{}{ +// "aaa": "aaa", +// } +// fmt.Println(toFloat64Reflect(data3)) +//} + +func TestToFloat64(t *testing.T) { + testCases := []struct { + value interface{} + expected float64 + expectedErr error + }{ + {nil, 0, nil}, + {float32(123.5), 123.5, nil}, + {"123.456", 123.456, nil}, + {uint(123), 123, nil}, + {uint8(123), 123, nil}, + {uint16(123), 123, nil}, + {uint32(123), 123, nil}, + {uint64(123), 123, nil}, + {int(123), 123, nil}, + {int8(123), 123, nil}, + {int16(123), 123, nil}, + {int32(123), 123, nil}, + {int64(123), 123, nil}, + {complex64(1 + 2i), 1, nil}, + {complex128(1 + 2i), 1, nil}, + {true, 1, nil}, + {false, 0, nil}, + {(*bool)(nil), 0, nil}, + } + + for _, tc := range testCases { + f, err := toFloat64(tc.value) + if f != tc.expected || err != tc.expectedErr { + t.Errorf("toFloat64(%v) = (%v, %v), expected (%v, %v)", tc.value, f, err, tc.expected, tc.expectedErr) + } + + f2, err2 := toFloat64Reflect(tc.value) + if f != tc.expected || err2 != tc.expectedErr { + t.Errorf("toFloat64Reflect(%v) = (%v, %v), expected (%v, %v)", tc.value, f2, err2, tc.expected, tc.expectedErr) + } + } +} + +func TestToFloat64Pointer(t *testing.T) { + testCases := []struct { + name string + input interface{} + expectedValue float64 + expectedError error + }{ + { + name: "nil input", + input: nil, + expectedValue: 0, + expectedError: nil, + }, + { + name: "float32 pointer input", + input: float32Ptr(12.2), + expectedValue: 12.199999809265137, + expectedError: nil, + }, + { + name: "float64 pointer input", + input: float64Ptr(56.78), + expectedValue: 56.78, + expectedError: nil, + }, + { + name: "invalid string input", + input: stringPtr("abc"), + expectedValue: 0, + expectedError: go_easy_utils.ErrSyntax, + }, + { + name: "valid string input", + input: stringPtr("123.45"), + expectedValue: 123.45, + expectedError: nil, + }, + { + name: "uint pointer input", + input: uintPtr(10), + expectedValue: 10, + expectedError: nil, + }, + { + name: "uint8 pointer input", + input: uint8Ptr(20), + expectedValue: 20, + expectedError: nil, + }, + { + name: "uint16 pointer input", + input: uint16Ptr(30), + expectedValue: 30, + expectedError: nil, + }, + { + name: "uint32 pointer input", + input: uint32Ptr(40), + expectedValue: 40, + expectedError: nil, + }, + { + name: "uint64 pointer input", + input: uint64Ptr(50), + expectedValue: 50, + expectedError: nil, + }, + { + name: "int pointer input", + input: intPtr(-60), + expectedValue: -60, + expectedError: nil, + }, + { + name: "int8 pointer input", + input: int8Ptr(-70), + expectedValue: -70, + expectedError: nil, + }, + { + name: "int16 pointer input", + input: int16Ptr(-80), + expectedValue: -80, + expectedError: nil, + }, + { + name: "int32 pointer input", + input: int32Ptr(-90), + expectedValue: -90, + expectedError: nil, + }, + { + name: "int64 pointer input", + input: int64Ptr(-100), + expectedValue: -100, + expectedError: nil, + }, + { + name: "complex64 pointer input", + input: complex64Ptr(complex(1, 2)), + expectedValue: 1, + expectedError: nil, + }, + { + name: "complex128 pointer input", + input: complex128Ptr(complex(3, 4)), + expectedValue: 3, + expectedError: nil, + }, + { + name: "bool pointer input - true", + input: boolPtr(true), + expectedValue: 1, + expectedError: nil, + }, + { + name: "bool pointer input - false", + input: boolPtr(false), + expectedValue: 0, + expectedError: nil, + }, + { + name: "unsupported input type", + input: "unsupported", + expectedValue: 0, + expectedError: go_easy_utils.ErrSyntax, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actualValue, actualError := toFloat64(tc.input) + + if actualError != tc.expectedError { + t.Errorf("Expected(name:%s) error: %v, but got: %v", tc.name, tc.expectedError, actualError) + } + + if !reflect.DeepEqual(actualValue, tc.expectedValue) { + t.Errorf("Expected value: %v, but got: %v", tc.expectedValue, actualValue) + } + + // Reflect + actualValue2, actualError2 := toFloat64Reflect(tc.input) + + if actualError2 != tc.expectedError { + t.Errorf("Expected(name:%s) error: %v, but got: %v", tc.name, tc.expectedError, actualError2) + } + + if !reflect.DeepEqual(actualValue2, tc.expectedValue) { + t.Errorf("Expected value: %v, but got: %v", tc.expectedValue, actualValue2) + } + }) + } +} + +func float32Ptr(v float32) *float32 { + return &v +} + +func float64Ptr(v float64) *float64 { + return &v +} + +func stringPtr(v string) *string { + return &v +} + +func uintPtr(v uint) *uint { + return &v +} + +func uint8Ptr(v uint8) *uint8 { + return &v +} + +func uint16Ptr(v uint16) *uint16 { + return &v +} + +func uint32Ptr(v uint32) *uint32 { + return &v +} + +func uint64Ptr(v uint64) *uint64 { + return &v +} + +func intPtr(v int) *int { + return &v +} + +func int8Ptr(v int8) *int8 { + return &v +} + +func int16Ptr(v int16) *int16 { + return &v +} + +func int32Ptr(v int32) *int32 { + return &v +} + +func int64Ptr(v int64) *int64 { + return &v +} + +func complex64Ptr(v complex64) *complex64 { + return &v +} + +func complex128Ptr(v complex128) *complex128 { + return &v +} + +func boolPtr(v bool) *bool { + return &v +} diff --git a/jsonUtil/to_int.go b/jsonUtil/to_int.go new file mode 100644 index 0000000..5c27328 --- /dev/null +++ b/jsonUtil/to_int.go @@ -0,0 +1,168 @@ +package jsonUtil + +import ( + "github.com/jefferyjob/go-easy-utils" + "reflect" + "strconv" +) + +func toInt64(i interface{}) (int64, error) { + if i == nil { + return 0, nil + } + + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return 0, nil + } + i = reflect.ValueOf(i).Elem().Interface() + } + + switch v := i.(type) { + case bool: + if v { + return 1, nil + } + return 0, nil + case uint: + return int64(v), nil + case uint8: + return int64(v), nil + case uint16: + return int64(v), nil + case uint32: + return int64(v), nil + case uint64: + return int64(v), nil + case float32: + return int64(v), nil + case float64: + return int64(v), nil + case complex64: + return int64(real(v)), nil + case complex128: + return int64(real(v)), nil + case string: + intValue, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return 0, go_easy_utils.ErrSyntax + } + return intValue, nil + case int: + return int64(v), nil + case int8: + return int64(v), nil + case int16: + return int64(v), nil + case int32: + return int64(v), nil + case int64: + return v, nil + //case *bool: + // if v == nil { + // return 0, nil + // } + // if *v { + // return 1, nil + // } + // return 0, nil + //case *uint: + // return int64(*v), nil + //case *uint8: + // return int64(*v), nil + //case *uint16: + // return int64(*v), nil + //case *uint32: + // return int64(*v), nil + //case *uint64: + // return int64(*v), nil + //case *float32: + // return int64(*v), nil + //case *float64: + // return int64(*v), nil + //case *complex64: + // if v == nil { + // return 0, nil + // } + // return int64(real(*v)), nil + //case *complex128: + // if v == nil { + // return 0, nil + // } + // return int64(real(*v)), nil + //case *string: + // if v == nil { + // return 0, nil + // } + // intValue, err := strconv.ParseInt(*v, 10, 64) + // if err != nil { + // return 0, go_easy_utils.ErrSyntax + // } + // return intValue, nil + //case *int: + // return int64(*v), nil + //case *int8: + // return int64(*v), nil + //case *int16: + // return int64(*v), nil + //case *int32: + // return int64(*v), nil + //case *int64: + // return *v, nil + default: + return 0, go_easy_utils.ErrType + } +} + +func toInt64Reflect(i interface{}) (int64, error) { + if i == nil { + return 0, nil + } + + // 检查解引用后的值是否为 nil + if reflect.ValueOf(i).Kind() == reflect.Ptr && reflect.ValueOf(i).IsNil() { + return 0, nil + } + + v := reflect.ValueOf(i) + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return 0, nil + } + v = reflect.ValueOf(i).Elem() + } + + switch v.Kind() { + case reflect.Float32, reflect.Float64: + return int64(v.Float()), nil + case reflect.String: + intValue, err := strconv.ParseInt(v.String(), 10, 64) + if err != nil { + return 0, go_easy_utils.ErrSyntax + } + return intValue, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return int64(v.Uint()), nil + case reflect.Complex64: + return int64(real(v.Complex())), nil + case reflect.Complex128: + return int64(real(v.Complex())), nil + case reflect.Bool: + if v.Bool() { + return 1, nil + } else { + return 0, nil + } + //case reflect.Ptr: + // if v.IsNil() { + // return 0, nil + // } + // return toInt64Reflect(v.Elem().Interface()) + default: + return 0, go_easy_utils.ErrType + } +} diff --git a/jsonUtil/to_int_test.go b/jsonUtil/to_int_test.go new file mode 100644 index 0000000..8e425cf --- /dev/null +++ b/jsonUtil/to_int_test.go @@ -0,0 +1,54 @@ +package jsonUtil + +import ( + "github.com/jefferyjob/go-easy-utils" + "testing" +) + +func TestToInt64(t *testing.T) { + var tests = []struct { + input interface{} + expected int64 + err error + }{ + {"123", 123, nil}, + {"-234", -234, nil}, + {345, 345, nil}, + {-456, -456, nil}, + {int8(12), 12, nil}, + {int16(1238), 1238, nil}, + {int32(1239), 1239, nil}, + {int64(1230), 1230, nil}, + {uint(1231), 1231, nil}, + {uint8(123), 123, nil}, + {uint16(1232), 1232, nil}, + {uint32(1233), 1233, nil}, + {uint64(1234), 1234, nil}, + {float32(12.45), 12, nil}, + {float64(123.45), 123, nil}, + {true, 1, nil}, + {false, 0, nil}, + {complex64(1 + 2i), 1, nil}, + {complex128(1 + 2i), 1, nil}, + {nil, 0, nil}, + {"not a number", 0, go_easy_utils.ErrSyntax}, + } + + for _, tt := range tests { + actual, err := toInt64(tt.input) + if err != tt.err { + t.Errorf("toInt64(%v): expected error %v, actual error %v", tt.input, tt.err, err) + } + if actual != tt.expected { + t.Errorf("toInt64(%v): expected %v, actual %v", tt.input, tt.expected, actual) + } + + actual, err = toInt64Reflect(tt.input) + if err != tt.err { + t.Errorf("toInt64(%v): expected error %v, actual error %v", tt.input, tt.err, err) + } + if actual != tt.expected { + t.Errorf("toInt64(%v): expected %v, actual %v", tt.input, tt.expected, actual) + } + } +} diff --git a/jsonUtil/to_string.go b/jsonUtil/to_string.go new file mode 100644 index 0000000..091664d --- /dev/null +++ b/jsonUtil/to_string.go @@ -0,0 +1,184 @@ +package jsonUtil + +import ( + "fmt" + "reflect" + "strconv" +) + +func toString(i interface{}) string { + if i == nil { + return "" + } + + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return "" + } + i = reflect.ValueOf(i).Elem().Interface() + } + + switch v := i.(type) { + case string: + return v + case int: + return strconv.Itoa(v) + case int8: + return strconv.FormatInt(int64(v), 10) + case int16: + return strconv.FormatInt(int64(v), 10) + case int32: + return strconv.FormatInt(int64(v), 10) + case int64: + return strconv.FormatInt(v, 10) + case uint: + return strconv.FormatUint(uint64(v), 10) + case uint8: + return strconv.FormatUint(uint64(v), 10) + case uint16: + return strconv.FormatUint(uint64(v), 10) + case uint32: + return strconv.FormatUint(uint64(v), 10) + case uint64: + return strconv.FormatUint(v, 10) + case float32: + return strconv.FormatFloat(float64(v), 'f', -1, 32) + case float64: + return strconv.FormatFloat(v, 'f', -1, 64) + case complex64: + return fmt.Sprintf("(%g+%gi)", real(v), imag(v)) + case complex128: + return fmt.Sprintf("(%g+%gi)", real(v), imag(v)) + case bool: + return strconv.FormatBool(v) + //case *string: + // if v == nil { + // return "" + // } + // return *v + //case *int: + // if v == nil { + // return "" + // } + // return strconv.Itoa(*v) + //case *int8: + // if v == nil { + // return "" + // } + // return strconv.FormatInt(int64(*v), 10) + //case *int16: + // if v == nil { + // return "" + // } + // return strconv.FormatInt(int64(*v), 10) + //case *int32: + // if v == nil { + // return "" + // } + // return strconv.FormatInt(int64(*v), 10) + //case *int64: + // if v == nil { + // return "" + // } + // return strconv.FormatInt(*v, 10) + //case *uint: + // if v == nil { + // return "" + // } + // return strconv.FormatUint(uint64(*v), 10) + //case *uint8: + // if v == nil { + // return "" + // } + // return strconv.FormatUint(uint64(*v), 10) + //case *uint16: + // if v == nil { + // return "" + // } + // return strconv.FormatUint(uint64(*v), 10) + //case *uint32: + // if v == nil { + // return "" + // } + // return strconv.FormatUint(uint64(*v), 10) + //case *uint64: + // if v == nil { + // return "" + // } + // return strconv.FormatUint(*v, 10) + //case *float32: + // if v == nil { + // return "" + // } + // return strconv.FormatFloat(float64(*v), 'f', -1, 32) + //case *float64: + // if v == nil { + // return "" + // } + // return strconv.FormatFloat(*v, 'f', -1, 64) + //case *complex64: + // if v == nil { + // return "" + // } + // return fmt.Sprintf("(%g+%gi)", real(*v), imag(*v)) + //case *complex128: + // if v == nil { + // return "" + // } + // return fmt.Sprintf("(%g+%gi)", real(*v), imag(*v)) + //case *bool: + // if v == nil { + // return "" + // } + // return strconv.FormatBool(*v) + default: + return "" + } +} + +func toStringReflect(i interface{}) string { + if i == nil { + return "" + } + + // 检查解引用后的值是否为 nil + if reflect.ValueOf(i).Kind() == reflect.Ptr && reflect.ValueOf(i).IsNil() { + return "" + } + + v := reflect.ValueOf(i) + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return "" + } + v = reflect.ValueOf(i).Elem() + } + + switch v.Kind() { + case reflect.String: + return v.String() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return strconv.FormatInt(v.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return strconv.FormatUint(v.Uint(), 10) + case reflect.Float32: + return strconv.FormatFloat(v.Float(), 'f', -1, 32) + case reflect.Float64: + return strconv.FormatFloat(v.Float(), 'f', -1, 64) + case reflect.Complex64: + return fmt.Sprintf("(%g+%gi)", real(v.Complex()), imag(v.Complex())) + case reflect.Complex128: + return fmt.Sprintf("(%g+%gi)", real(v.Complex()), imag(v.Complex())) + case reflect.Bool: + return strconv.FormatBool(v.Bool()) + //case reflect.Ptr: + // if v.IsNil() { + // return "" + // } + // return toStringReflect(v.Elem().Interface()) + default: + return "" + } +} diff --git a/jsonUtil/to_string_test.go b/jsonUtil/to_string_test.go new file mode 100644 index 0000000..11a0c86 --- /dev/null +++ b/jsonUtil/to_string_test.go @@ -0,0 +1,41 @@ +package jsonUtil + +import "testing" + +func TestToString(t *testing.T) { + tests := []struct { + name string + value interface{} + want string + }{ + {"nil", nil, ""}, + {"string", "hello", "hello"}, + {"int", 42, "42"}, + {"int8", int8(42), "42"}, + {"int16", int16(42), "42"}, + {"int32", int32(42), "42"}, + {"int64", int64(42), "42"}, + {"uint", uint(42), "42"}, + {"uint8", uint8(42), "42"}, + {"uint16", uint16(42), "42"}, + {"uint32", uint32(42), "42"}, + {"uint64", uint64(42), "42"}, + {"float32", float32(3.14159), "3.14159"}, + {"float64", 3.14159, "3.14159"}, + {"bool-true", true, "true"}, + {"bool-false", false, "false"}, + {"complex64", complex64(1 + 2i), "(1+2i)"}, + {"complex128", complex128(3 + 4i), "(3+4i)"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := toString(tt.value); got != tt.want { + t.Errorf("ToString() = %v, want %v", got, tt.want) + } + + if got := toStringReflect(tt.value); got != tt.want { + t.Errorf("ToString() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/jsonUtil/to_uint.go b/jsonUtil/to_uint.go new file mode 100644 index 0000000..c7f5e71 --- /dev/null +++ b/jsonUtil/to_uint.go @@ -0,0 +1,223 @@ +package jsonUtil + +import ( + "github.com/jefferyjob/go-easy-utils" + "reflect" + "strconv" +) + +func toUint64(i interface{}) (uint64, error) { + if i == nil { + return 0, nil + } + + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return 0, nil + } + i = reflect.ValueOf(i).Elem().Interface() + } + + switch v := i.(type) { + case float32: + if v < 0 { + return 0, nil + } + return uint64(v), nil + case float64: + if v < 0 { + return 0, nil + } + return uint64(v), nil + case complex64: + if real(v) < 0 || imag(v) < 0 { + return 0, nil + } + return uint64(real(v)), nil + case complex128: + if real(v) < 0 || imag(v) < 0 { + return 0, nil + } + return uint64(real(v)), nil + case string: + intValue, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return 0, go_easy_utils.ErrSyntax + } + return intValue, nil + case bool: + if v { + return 1, nil + } else { + return 0, nil + } + case uint: + return uint64(v), nil + case uint8: + return uint64(v), nil + case uint16: + return uint64(v), nil + case uint32: + return uint64(v), nil + case uint64: + return v, nil + case int: + if v < 0 { + return 0, nil + } + return uint64(v), nil + case int8: + if v < 0 { + return 0, nil + } + return uint64(v), nil + case int16: + if v < 0 { + return 0, nil + } + return uint64(v), nil + case int32: + if v < 0 { + return 0, nil + } + return uint64(v), nil + case int64: + if v < 0 { + return 0, nil + } + return uint64(v), nil + //case *float32: + // if *v < 0 { + // return 0, nil + // } + // return uint64(*v), nil + //case *float64: + // if *v < 0 { + // return 0, nil + // } + // return uint64(*v), nil + //case *complex64: + // if real(*v) < 0 || imag(*v) < 0 { + // return 0, nil + // } + // return uint64(real(*v)), nil + //case *complex128: + // if real(*v) < 0 || imag(*v) < 0 { + // return 0, nil + // } + // return uint64(real(*v)), nil + //case *string: + // intValue, err := strconv.ParseUint(*v, 10, 64) + // if err != nil { + // return 0, go_easy_utils.ErrSyntax + // } + // return intValue, nil + //case *bool: + // if *v { + // return 1, nil + // } else { + // return 0, nil + // } + //case *uint: + // return uint64(*v), nil + //case *uint8: + // return uint64(*v), nil + //case *uint16: + // return uint64(*v), nil + //case *uint32: + // return uint64(*v), nil + //case *uint64: + // return *v, nil + //case *int: + // if *v < 0 { + // return 0, nil + // } + // return uint64(*v), nil + //case *int8: + // if *v < 0 { + // return 0, nil + // } + // return uint64(*v), nil + //case *int16: + // if *v < 0 { + // return 0, nil + // } + // return uint64(*v), nil + //case *int32: + // if *v < 0 { + // return 0, nil + // } + // return uint64(*v), nil + //case *int64: + // if *v < 0 { + // return 0, nil + // } + // return uint64(*v), nil + default: + return 0, go_easy_utils.ErrType + } +} + +func toUint64Reflect(i interface{}) (uint64, error) { + if i == nil { + return 0, nil + } + + // 检查解引用后的值是否为 nil + if reflect.ValueOf(i).Kind() == reflect.Ptr && reflect.ValueOf(i).IsNil() { + return 0, nil + } + + v := reflect.ValueOf(i) + // 处理指针类型 + if reflect.TypeOf(i).Kind() == reflect.Ptr { + if reflect.ValueOf(i).IsNil() { + return 0, nil + } + v = reflect.ValueOf(i).Elem() + } + + switch v.Kind() { + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint(), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + intValue := v.Int() + if intValue < 0 { + return 0, nil + } + return uint64(intValue), nil + case reflect.Float32, reflect.Float64: + floatValue := v.Float() + if floatValue < 0 { + return 0, nil + } + return uint64(floatValue), nil + case reflect.Complex64, reflect.Complex128: + realValue := real(v.Complex()) + if realValue < 0 { + return 0, nil + } + return uint64(realValue), nil + case reflect.String: + strValue := v.String() + uintValue, err := strconv.ParseUint(strValue, 10, 64) + if err != nil { + return 0, go_easy_utils.ErrSyntax + } + return uintValue, nil + case reflect.Bool: + if v.Bool() { + return 1, nil + } else { + return 0, nil + } + //case reflect.Ptr, reflect.Interface: + // if v.IsNil() { + // return 0, nil + // } + // return toUint64(v.Elem().Interface()) + default: + return 0, go_easy_utils.ErrType + } +} diff --git a/jsonUtil/to_uint_test.go b/jsonUtil/to_uint_test.go new file mode 100644 index 0000000..34066a3 --- /dev/null +++ b/jsonUtil/to_uint_test.go @@ -0,0 +1,128 @@ +package jsonUtil + +import ( + "github.com/jefferyjob/go-easy-utils" + "testing" +) + +func TestToUint64(t *testing.T) { + tests := []struct { + name string + input interface{} + want uint64 + wantError error + }{ + { + name: "Test uint8", + input: uint8(42), + want: 42, + }, + { + name: "Test uint16", + input: uint16(42), + want: 42, + }, + { + name: "Test uint32", + input: uint32(42), + want: 42, + }, + { + name: "Test uint64", + input: uint64(42), + want: 42, + }, + { + name: "Test int8", + input: int8(42), + want: 42, + }, + { + name: "Test int16", + input: int16(42), + want: 42, + }, + { + name: "Test int32", + input: int32(42), + want: 42, + }, + { + name: "Test int64", + input: int64(42), + want: 42, + }, + { + name: "Test float32", + input: float32(42.0), + want: 42, + }, + { + name: "Test float64", + input: float64(42.0), + want: 42, + }, + { + name: "Test complex64", + input: complex64(complex(42, 0)), + want: 42, + }, + { + name: "Test complex128", + input: complex128(complex(42, 0)), + want: 42, + }, + { + name: "Test string", + input: "42", + want: 42, + }, + { + name: "Test invalid string", + input: "not a number", + wantError: go_easy_utils.ErrSyntax, + }, + { + name: "Test nil pointer", + input: (*int)(nil), + want: 0, + wantError: nil, + }, + { + name: "Test bool true", + input: true, + want: 1, + }, + { + name: "Test bool false", + input: false, + want: 0, + }, + { + name: "Test invalid type", + input: make(chan int), + wantError: go_easy_utils.ErrType, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := toUint64(tt.input) + if err != tt.wantError { + t.Errorf("toUint64(%v) error = %v, wantError %v", tt.input, err, tt.wantError) + } + if got != tt.want { + t.Errorf("toUint64(%v) = %v, want %v", tt.input, got, tt.want) + } + + // Reflect + got2, err2 := toUint64Reflect(tt.input) + if err2 != tt.wantError { + t.Errorf("toUint64Reflect(%v) error = %v, wantError %v", tt.input, err2, tt.wantError) + } + if got2 != tt.want { + t.Errorf("toUint64Reflect(%v) = %v, want %v", tt.input, got2, tt.want) + } + }) + } +}