【问题标题】:Struct value of pointer, array and slice指针、数组和切片的结构值
【发布时间】:2014-08-03 22:43:30
【问题描述】:

我想要一个通用的方式,无论它是作为指针、切片还是数组提供,它总是返回结构值。

我对此的看法:

func main() {
    p := Person{}

    if value(p).Kind() != reflect.Struct {
        fmt.Printf("Error 1")
    }
    if value(&p).Kind() != reflect.Struct {
        fmt.Printf("Error 2")
    }   
    if value([]Person{p}).Kind() != reflect.Struct {
        fmt.Printf("Error 3")
    }
    if value(&[]Person{p}).Kind() != reflect.Struct {
        fmt.Printf("Error 4")
    }
}

func value(m interface{}) reflect.Value {
    v := reflect.ValueOf(m)

    switch v.Kind() {
    case reflect.Ptr:
        v = v.Elem()

        fallthrough
    case reflect.Slice, reflect.Array:
        v = v.Elem()
    }

    return v
}

Go Playground

如您所见,问题在于将结构从slicearray 中取出。

如何扩展上述函数以从数组或切片中获取结构值?

更新:我想做的是将[]People 变成People

【问题讨论】:

  • 您不能只将[]People 变成People,因为[]People 可以包含许多People 对象,并且(通常)没有合理的方法来合并对象。尝试只选择一个(第一个?)。还有如果切片是空的怎么办?
  • 我很确定他正在尝试获取结构字段。

标签: reflection go


【解决方案1】:

如果即使切片为 nil 也只想要类型,则可以使用 this 之类的东西:

func value(m interface{}) reflect.Type {
    t := reflect.Indirect(reflect.ValueOf(m)).Type()
    if t.Kind() == reflect.Slice || t.Kind() == reflect.Array {
        t = t.Elem()
        if t.Kind() == reflect.Ptr {
            t = t.Elem()
        }
        return t

    }
    return t
}

关于Type.Elem(),来自http://golang.org/pkg/reflect/#Type

// Elem 返回一个类型的元素类型。

// 如果类型的 Kind 不是 Array、Chan、Map、Ptr 或 Slice,它会恐慌。

//edit 更新了函数以处理指针切片。

【讨论】:

  • 正是我想要的。 .Elem() 有什么规定吗?我在看到其使用模式时遇到问题。
  • 它只适用于 Array、Chan、Map、Ptr 或 Slice,我添加了参考。
  • @bodokaiser 我已经更新了函数以在 []*Person(nil) 上工作
【解决方案2】:

我假设您所说的“离开切片或数组”的意思是您想要第一个元素(即索引 0 处的元素)?如果这就是你想要的,那么你应该使用reflect.Value.Index() 方法。例如:

func value(m interface{}) reflect.Value {
    v := reflect.ValueOf(m)

    switch v.Kind() {
    case reflect.Ptr:
        v = v.Elem()
        if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
            v = v.Index(0)
        }
    case reflect.Slice, reflect.Array:
        v = v.Index(0)
    default:
        break LOOP
    }

    return v
}

Go playground

请注意,我还稍微修改了流程逻辑。您正在从指针案例陷入切片/数组案例。您可能打算再次测试 case 条件(所以它实际上会说,“如果这是一个指针,现在检查它指向的东西是切片还是数组”),但这不是 fallthrough 的工作方式。现在它明确地检查大小写。

【讨论】:

    猜你喜欢
    • 2015-02-21
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 2019-11-10
    相关资源
    最近更新 更多