统一信息返回的优雅处理| 青训营笔记

129 阅读1分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记

前言

在gin项目中,我们都需要将后端信息用json格式响应给前端调用者。 这时候我们可能会封装一个struct作为统一的信息处理。

但是面对格式不一的返回结构,我们就很难用一个struct表达所有类型 比如:

image.png

再比如:

image.png

前端的请求json格式是多变的,我们无法用一个统一的struct表达它们。这样的话我们就要为每一个请求都写一个struct接收,这样无疑是痛苦的,冗余代码很多

使用反射生成对应的json格式

“办法总比困难多”,我们可以借助golang的反射解决这个问题

思路

  1. 使用统一的BasicResponse来接收参数
  2. 将BasicResponse的参数逐个展开,并将其转换为map结构
  3. 最后将map结构转换为json,响应给前端

代码

func struct2Map(in interface{}) map[string]interface{} {

   // 当前函数只接收struct类型
   v := reflect.ValueOf(in)
   if v.Kind() == reflect.Ptr { // 结构体指针
      v = v.Elem()
   }

   out := make(map[string]interface{}, 8)
   queue := make([]interface{}, 0, 1)
   queue = append(queue, in)

   for len(queue) > 0 {
      v := reflect.ValueOf(queue[0])
      if v.Kind() == reflect.Ptr { // 结构体指针
         v = v.Elem()
      }
      queue = queue[1:]
      t := v.Type()
      for i := 0; i < v.NumField(); i++ {
         vi := v.Field(i)
         if vi.Kind() == reflect.Interface { // interface; data部分
            queue = append(queue, vi.Interface())
            break
         }
         // 一般字段
         ti := t.Field(i)
         if tagValue := ti.Tag.Get("json"); tagValue != "" {
            // 存入map
            out[tagValue] = vi.Interface()
         }
      }
   }
   return out
}