代码之家  ›  专栏  ›  技术社区  ›  learningtech

reflect.New()生成的切片的JSON封送在golang中为null

  •  3
  • learningtech  · 技术社区  · 6 年前

    我正在使用golang中的reflect来制作一个新的初始化切片。但是当我处理这个新的反射片段的时候,我得到了一个json null 值而不是 [] . 看这个例子,我比较了两种情况:

    package main
    
    import (
      "encoding/json"
      "reflect"
      "log"
    )
    func makeslice(slice interface{}) interface{} {
    
      return reflect.New(reflect.TypeOf(slice)).Elem().Interface()
    }
    func main() {
    
      s0 := []int{2,3,5}
    
      s1 := makeslice(s0).([]int)
      js1,e1 := json.Marshal(s1)
      log.Println("case 1:",reflect.TypeOf(s1),reflect.ValueOf(s1),e1,string(js1))
    
      s2 := []int{}
      js2,e2 := json.Marshal(s2)
      log.Println("case 2:",reflect.TypeOf(s2),reflect.ValueOf(s2),e2,string(js2))
    
    }
    

    这将产生以下输出:

    case 1: []int [] <nil> null
    case 2: []int [] <nil> []
    

    case 1 case 2 无效的 第二个案例显示 .

    案例1 显示 [] 相反,因为我朋友的客户端应用程序总是需要一个数组,而长度为零的数组不应该显示为null。

    我做错什么了?

    1 回复  |  直到 6 年前
        1
  •  7
  •   novalagung Alexander Kim    5 年前

    什么 reflect.New() 是否按照 documentation :

    在你的代码里,两者都是 s0 s2 不是零。但是 s1 []int 类型,即 nil reflect.New() .

    下面的代码证明了切片零值 .

    var a []int = []int{}
    log.Printf("%#v \n", a) // ====> []int{}
    
    var b []int
    log.Printf("%#v \n", b) // ====> []int(nil)
    

    我建议用 reflect.MakeSlice() 而不是做一片。生成的值不会是

    func makeslice(slice interface{}) interface{} {
        return reflect.MakeSlice(reflect.TypeOf(slice), 0, 0).Interface()
    }
    

    然后根据您的代码,输出将是:

    case 1: []int [] <nil> []
    case 2: []int [] <nil> []
    

    工作场所: https://play.golang.org/p/tL3kFqVwOtC


    转换 []内景 具有 将值转换为JSON null . 但是转换 []int{} 将数据转换为JSON []


    作为注释的后续,此方法生成一个可寻址切片,可以使用reflect进一步修改该切片:

    func makeslice(slice interface{}) interface{} {
        newsliceval := reflect.MakeSlice(reflect.TypeOf(slice),0,0)
        newslice := reflect.New(newsliceval.Type()).Elem()
        newslice.Set(newsliceval)
    
        /*
         * make any desired changes to newslice with reflect package
         */
    
        return newslice.Interface()
    }
    

    这里有更多的解释 Why golang reflect.MakeSlice returns un-addressable Value