为了账号安全,请及时绑定邮箱和手机立即绑定

通过反射提取通用结构值

通过反射提取通用结构值

Go
繁华开满天机 2022-06-01 17:44:20
我正在尝试将结构的所有值提取到字符串切片中。func structValues(item Item) []string {    values := []string{}    e := reflect.ValueOf(&item).Elem()    for i := 0; i < e.NumField(); i++ {        fieldValue := e.Field(i).Interface()        values = append(values, fmt.Sprintf("%#v", fieldValue))    }    return values}我想将此函数与任何结构一起使用,所以我想我可以将类型签名更改为,func structValues(item interface{})但后来我感到恐慌:恐慌:反射:在接口值上调用反射.Value.NumField工作示例:https ://repl.it/@fny/stackoverflow61719532去
查看完整描述

1 回答

?
噜噜哒

TA贡献1784条经验 获得超7个赞

我想将此函数与任何结构一起使用...


您可以这样做,但请注意它放弃了类型安全。此外,这样做的唯一方法是允许使用任何类型的调用,而不仅仅是某种结构类型的任何类型,所以你必须检查你得到的实际上是某种结构类型:


func structValues(item interface{}) {

    if reflect.ValueOf(item).Kind() != reflect.Struct {

        ... do something here ...

    }

进行了检查——或者稍微推迟它,或者省略它以允许reflect恐慌——然后你需要reflect.ValueOf(&item).Elem()用更简单的reflect.ValueOf(item).


如果您希望允许指向结构以及实际结构的指针,您可以通过使用reflect.Indirectfirst. 结果是:


func structValues(item interface{}) []string {

    e := reflect.Indirect(reflect.ValueOf(item))

    if e.Kind() != reflect.Struct {

        panic("not a struct")

    }

    values := []string{}

    for i := 0; i < e.NumField(); i++ {

        fieldValue := e.Field(i).Interface()

        values = append(values, fmt.Sprintf("%#v", fieldValue))

    }

    return values

}

reflect.Indirect如果您想确保调用者在有指针时执行自己的间接操作,请忽略。


(注意panic这里不是很友好。如果你想要正确的调试,考虑直接用%vor打印结构%#v,或者更彻底的东西,spew 包。)


Go Playground 上的完整示例使用您type Item struct自己的链接。


查看完整回答
反对 回复 2022-06-01
  • 1 回答
  • 0 关注
  • 120 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号