Go開發(fā)中結(jié)構(gòu)體 model、dto 、time格式問題
1、背景
model層不允許使用 json, dto層又重復(fù)造輪子,一個(gè)表的字段可能20個(gè)左右,那么賦值語句難受死了。
其次就是json直接解析,model層的time.Time,完蛋格式不對(duì),返回的數(shù)據(jù)不對(duì)。
比如
- {
- "user_name": "xiaoli",
- "create_time": "2020-06-05T13:53:06.293614+08:00"
- }
這種情況,無法解決,就需要必須重寫一個(gè)dto。
那么如何解決這個(gè)問題呢,本人思考了一段時(shí)間,最終使用Map來解決。
2、解決問題
1、反射
那么反射會(huì)遇到,各種奇葩的書寫方式,有些人什么都出傳入指針,有些人各種interface{} 隱藏轉(zhuǎn)換,反正就是太過于差異化。
所以就是需要解決,如何準(zhǔn)確的拿到Value對(duì)象,下面是我寫的一個(gè)工具類
- 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
- // 所以這里需要將它轉(zhuǎn)換
- if value.CanInterface() {
- return GetRealValue(reflect.ValueOf(value.Interface()))
- }
- return GetRealValue(value.Elem())
- }
- return value
- }
解決這個(gè)問題,開干
2、下劃線命名法
下劃線如何解決,結(jié)構(gòu)體的字段屬于駝峰命名法,怎么解決呢?
寫了一個(gè)簡(jiǎn)單的工具類
問題:
- 如果是ID,連續(xù)大寫,輸出i_d
- 因?yàn)閿?shù)組到切片需要拷貝一次,所以可以利用unsafe解決,因?yàn)樽址讓泳褪乔衅?,但是不安?/li>
- 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'
- }
3、開干
- 解決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
- }
4、測(cè)試
- 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)
- }
輸出結(jié)果:
完美,美中不足是需要使用likedMap,由于Golang源碼包沒有,所以,注定亂序
- {"create_time":"2020-06-05 14:05:31","user_name":"xiaoli"}