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

无法设置类型为接口的结构的字段{}

无法设置类型为接口的结构的字段{}

Go
慕桂英3389331 2023-03-29 15:34:11
我一直在为反射包而苦苦挣扎。下面的代码符合我的预期:package mainimport (  "reflect"  "log")type Car struct {  Model string}type Person struct {  Name string  Cars []Car}func ModifyIt(parent interface{},fieldName string, val interface{}) {  slice := reflect.ValueOf(parent).Elem()  nth := slice.Index(0)  //row := nth.Interface() // this line causes errors  row := nth.Interface().(Person)  elem := reflect.ValueOf(&row).Elem()  field := elem.FieldByName(fieldName)  log.Println(field.CanSet())}func main() {  p := []Person{Person{Name:"john"}}  c := []Car{Car{"corolla"},Car{"jetta"}}  ModifyIt(&p,"Cars",&c)}row := nth.Interface().(Person)但是,如果我用替换该行row := nth.Interface(),即删除类型断言,则会收到错误:恐慌:反映:在接口值上调用 reflect.Value.FieldByName on line "field := elem.FieldByName(fieldName)在过去的几个小时里,我尝试了很多其他的事情,比如尝试reflect.TypeOf()对reflect.Indirect()其他一些变量做等等,但没有成功。我的问题是,当结构被键入为接口时,我该如何设置结构的字段?
查看完整描述

2 回答

?
HUWWW

TA贡献1874条经验 获得超12个赞

尝试这个:


func ModifyIt(slice interface{}, fieldName string, newVal interface{}) {

    // Create a value for the slice.

    v := reflect.ValueOf(slice)


    // Get the first element of the slice.

    e := v.Index(0)


    // Get the field of the slice element that we want to set.

    f := e.FieldByName(fieldName)


    // Set the value!

    f.Set(reflect.ValueOf(newVal))

}

像这样称呼它:


p := []Person{Person{Name: "john"}}

c := []Car{Car{"corolla"}, Car{"jetta"}}

ModifyIt(p, "Cars", c)

请注意,调用直接传递切片而不是使用指向切片的指针。不需要指针并增加了额外的复杂性。



查看完整回答
反对 回复 2023-03-29
?
暮色呼如

TA贡献1853条经验 获得超9个赞

纯粹出于运气,我终于得到了一些工作。


我拼凑了一堆随机阅读的东西,几乎没有韵律或理由。我什至尝试阅读 Golang 网站上的反射法则,但我认为我没有很好地理解它与为什么我不能将变量类型设置为interface{}. 总的来说,我还是不明白我做了什么。


我在下面的解决方案中充斥着评论,表明我很困惑,并且对我是否正确或安全地做事缺乏信心。


package main


import (

  "reflect"

  "log"

)

type Car struct {

  Model string

}

type Person struct {

  Name string

  Cars []Car

}


func ModifyIt(parent interface{},fieldName string, val interface{}) {

  log.Println(parent)

  slice := reflect.ValueOf(parent).Elem()

  nth := slice.Index(0)

  row := nth.Interface()

  log.Println(nth.CanSet()) // I can set this nth item


  // I think I have a to make a copy, don't fully understand why this is necessary

  newitem := reflect.New(reflect.ValueOf(row).Type())

  newelem := newitem.Elem()

  field := newelem.FieldByName(fieldName)


  // I need to copy the values over from the old nth row to this new item

  for c:=0; c<nth.NumField(); c++ {

    newelem.Field(c).Set(reflect.Indirect(nth.Field(c)))

  }


  // now I can finally set the field for some reason I don't understand

  field.Set(reflect.ValueOf(val).Elem())


  // now that newitem has new contents in the field object, I need to overwrite the nth item with new item

  // I don't know why I'm doing it, but I'll do it

  // I also don't fully understand why I have to use Indirect sometimes, and not other times...it seems interchangeable with ValueOf(something).Elem(), I'm confused....

  nth.Set(reflect.Indirect(newitem))


}


func main() {


  p := []Person{Person{Name:"john"}}

  c := []Car{Car{"corolla"},Car{"jetta"}}


  ModifyIt(&p,"Cars",&c)

  // now parent is up to date, although I have no idea how I got here.

  log.Println(p)

}

如果有人可以发布更好的答案来消除我的困惑,那就太好了。我一直很难学习 golang。


查看完整回答
反对 回复 2023-03-29
  • 2 回答
  • 0 关注
  • 93 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信