【问题标题】:interface{} variable to []interface{}interface{} 变量到 []interface{}
【发布时间】:2016-05-21 02:37:09
【问题描述】:

我有一个interface{} 变量,我知道它是一个指向切片的指针:

func isPointerToSlice(val interface{}) bool {
    value := reflect.ValueOf(val)
    return value.Kind() == reflect.Ptr && value.Elem().Kind() == reflect.Slice
}

但我发现很难将其类型转换为 []interface{} 变量:

if isPointerToSlice(val) {
  slice, worked := reflect.ValueOf(val).Elem().Interface().([]interface{})
  // 'worked' is false :(
}

这不起作用。知道如何解决这个问题吗?

【问题讨论】:

    标签: go reflection interface slice type-assertion


    【解决方案1】:

    您可以简单地使用type assertion 来获取存储在接口中的值,例如

    if isPointerToSlice(val) {
        var result []interface{}
        result = *val.(*[]interface{})
        fmt.Println(result)
    } else {
        fmt.Println("Not *[]interface{}")
    }
    

    您声称的存储在接口中的值的类型是指向[]interface{}的指针,即*[]interface{}。类型断言的结果将是一个指针,只需解引用它即可获得切片[]interface{}

    使用short variable declaration

    result := *val.(*[]interface{}) // type of result is []interface{}
    

    Go Playground 上试试。


    你的尝试也有效:

    slice, worked := reflect.ValueOf(val).Elem().Interface().([]interface{})
    fmt.Println(slice, worked)
    

    这是证明您的解决方案有效的edited the Playground example

    但是使用反射是不必要的(因为它可以通过类型断言来完成)。

    还要注意*[]interface{}*[]someOtherType 是两种不同的类型,如果val 中有其他内容,则无法获得*[]interface{} 的值。

    【讨论】:

    • @izca,在我的特定示例中,它失败并出现此错误interface conversion: interface {} is *[]util.sample, not *[]interface {}
    • @PabloFernandez *[]util.sample*[]interface{} 是两种不同的类型。如果您的val 包含*[]util.sample 类型的值,则只能从中获取*[]util.sample 的值。
    【解决方案2】:

    Icza 的回答很棒,特别是如果你不能确定你得到了一个接口切片,但是如果你根本不想打扰反射包并且想要保持低导入代码,你可以使用类型切换来仅使用内置方法获得相同的功能。

    使用此方法,您可以将代码缩短为:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        s := []interface{}{"one", 2}
        p := &s
    
        do(p)
    }
    
    func do(val interface{}) {
        switch val.(type){
        case *[]interface{}:
            var result []interface{}
            result = *val.(*[]interface{})
            fmt.Println(result)
        }
    }
    

    游乐场:http://play.golang.org/p/DT_hb8JcVt

    不利的一面是,如果您事先不知道您收到的切片的确切类型,那么除非您列出所有可能的处理和断言类型,否则这将不起作用。

    【讨论】:

      【解决方案3】:

      如果您只想将切片转换为[]interface{},您可以使用以下内容:

      func sliceToIfaceSlice(val interface{}) []interface{} {
          rf := reflect.Indirect(reflect.ValueOf(val)) // skip the pointer
          if k := rf.Kind(); k != reflect.Slice && k != reflect.Array {
              // panic("expected a slice or array")
              return nil
          }
          out := make([]interface{}, rf.Len())
          for i := range out {
              out[i] = rf.Index(i).Interface()
          }
          return out
      }
      

      playground

      【讨论】:

        猜你喜欢
        • 2016-09-18
        • 2020-03-03
        • 2017-08-02
        • 1970-01-01
        • 2014-09-16
        • 1970-01-01
        • 2017-04-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多