Go開發(fā)中結構體 model、dto 、time格式問題
1、背景
model層不允許使用 json, dto層又重復造輪子,一個表的字段可能20個左右,那么賦值語句難受死了。
其次就是json直接解析,model層的time.Time,完蛋格式不對,返回的數(shù)據(jù)不對。
比如
- {
 - "user_name": "xiaoli",
 - "create_time": "2020-06-05T13:53:06.293614+08:00"
 - }
 
這種情況,無法解決,就需要必須重寫一個dto。
那么如何解決這個問題呢,本人思考了一段時間,最終使用Map來解決。
2、解決問題
1、反射
那么反射會遇到,各種奇葩的書寫方式,有些人什么都出傳入指針,有些人各種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
 - }
 
解決這個問題,開干
2、下劃線命名法
下劃線如何解決,結構體的字段屬于駝峰命名法,怎么解決呢?
寫了一個簡單的工具類
問題:
- 如果是ID,連續(xù)大寫,輸出i_d
 - 因為數(shù)組到切片需要拷貝一次,所以可以利用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'
 - }
 
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、測試
- 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"}
 















 
 
 










 
 
 
 