model層不容許申明json tag, dto層又重複造輪子,一個表的字段可能20個左右,那麼賦值語句難受死了。git
其次就是json直接解析,model層的time.Time,完蛋格式不對,返回的數據不對。json
好比數組
{
"user_name": "xiaoli",
"create_time": "2020-06-05T13:53:06.293614+08:00"
}
複製代碼
這種狀況,沒法解決,就須要必須重寫一個dto。安全
那麼如何解決這個問題呢,本人思考了一段時間,最終使用Map來解決。app
那麼反射會遇到,各類奇葩的書寫方式,有些人什麼都出傳入指針,有些人各類interface{} 隱藏轉換,反正就是太過於差別化。工具
因此就是須要解決,如何準確的拿到Value對象,下面是我寫的一個工具類測試
func GetRealValue(value reflect.Value) reflect.Value {
kind := value.Kind()
if kind == reflect.Ptr {
return GetRealValue(value.Elem())
}
if kind == reflect.Interface {
// eg:var s2 interface{}
// s2 = User{}
// fmt.Println(reflect.ValueOf(&s2).Elem().Kind())// interface
// 因此這裏須要將它轉換
if value.CanInterface() {
return GetRealValue(reflect.ValueOf(value.Interface()))
}
return GetRealValue(value.Elem())
}
return value
}
複製代碼
解決這個問題,開幹ui
下劃線如何解決,結構體的字段屬於駝峯命名法,怎麼解決呢,爲此。spa
寫了一個簡單的工具類指針
問題:一、若是是ID
,連續大寫,輸出i_d
二、由於數組到切片須要拷貝一次,因此能夠利用unsafe解決,由於字符串底層就是切片,可是不安全
func CamelCase(s string) string {
if s == "" {
return ""
}
t := make([]byte, 0, 32)
i := 0
for ; i < len(s); i++ {
c := s[i]
if isASCIIDigit(c) {
t = append(t, c)
continue
}
if isASCIIUpper(c) {
c ^= ' '
}
t = append(t, c)
for i+1 < len(s) && isASCIIUpper(s[i+1]) {
i++
t = append(t, '_', s[i]+32)
}
}
//return *(*string)(unsafe.Pointer(&t))
return string(t)
}
func isASCIIUpper(c byte) bool {
return 'A' <= c && c <= 'Z'
}
func isASCIIDigit(c byte) bool {
return '0' <= c && c <= '9'
}
複製代碼
一、解決time的問題
二、反射、下劃線命名法
func ToStdMap(bean interface{}) map[string]interface{} {
_value := GetRealValue(reflect.ValueOf(bean))
if _value.Kind() != reflect.Struct {
panic("the bean mush struct")
}
_type := _value.Type()
fieldNum := _value.NumField()
_map := make(map[string]interface{}, fieldNum)
for x := 0; x < fieldNum; x++ {
field := _type.Field(x)
value := GetRealValue(_value.Field(x))
if value.CanInterface() {
realValue := value.Interface()
switch realValue.(type) {
case time.Time:
_map[CamelCase(field.Name)] = times.FormatStdTime(realValue.(time.Time))
default:
_map[CamelCase(field.Name)] = realValue
}
}
}
return _map
}
複製代碼
func TestObjToMap(t *testing.T) {
users := Users{
UserName: "xiaoli",
}
now := time.Now()
users.CreateTime = &now
stdMap := ToStdMap(users)
bytes, err := json.Marshal(stdMap)
if err != nil {
t.Fatal(err)
}
fmt.Printf("%s\n", bytes)
}
複製代碼
輸出結果:
完美,美中不足是須要使用likedMap,因爲Golang源碼包沒有,因此😓,註定亂序
{"create_time":"2020-06-05 14:05:31","user_name":"xiaoli"}
複製代碼