【问题标题】:Set interface values returned by interface method with reflect使用反射设置接口方法返回的接口值
【发布时间】:2021-07-27 00:53:47
【问题描述】:

给定一个返回指针类型切片但包装为接口类型的接口。是否可以修改值?

type Base interface {
    Do()
}

type Meta interface {
    Base
    Children() []Base
}

type A struct {
}

func (a *A) Do() {
}

type B struct {
    children []Base
}

func (b *B) Children() []Base {
    return b.children
}

如果代码以如下方式初始化:

a := &A{}
b := &B{children: []Base{a}}

是否可以仅使用调用b.Children() 和使用反射后返回的值覆盖B.children 的值?或者那不可能?

https://play.golang.net/p/rvMsdVNLQ6a

【问题讨论】:

  • 这是有道理的,但如果实施者决定返回一个新分配的切片,它将建立在失败的假设之上。将其作为答案发布,以便我接受?
  • 为什么不在Meta接口中增加一个设置children的方法?
  • @advayrajhansa 很好的建议,我一直在考虑,但有时子元素不存储为切片,而是结构中的几个单独元素,然后设置变得更加困难一个可以工作的接口:例如,获取和设置子项需要以相同的顺序设置和返回它们。
  • 在给定的上下文中,我认为interfaces 不是前进的道路。如果您直接需要确定的结构(如果需要,绝对可以使用反射),那么我认为最好不要用接口包装它。不确定全貌,我认为工厂模式可能会有所帮助。如果没有,reflect 可以提供帮助。
  • 从你开始尝试模仿传统 OOP 继承的那一刻起,你就开始失败了。绝对没有办法让一种继承在 Go 中工作。

标签: go reflect


【解决方案1】:

接口方法Children() []Base从底层结构返回切片头的副本。可以修改切片的元素,但不能修改接口引用的对象中包含的切片。

如果你有一个Meta类型的变量,你可以使用类型断言来检查底层对象是否是*B,如果是,直接从同一个包中访问children

更改切片的一种方法是添加另一个接口来执行此操作:

type childrenSetter interface {
   SetChildren([]Base)
}

...
if setter, ok:=intf.(childrenSetter); ok {
   setter.SetChildren(newChildren)
}

这只有在底层类型实现SetChildren 方法时才有效。

【讨论】:

    猜你喜欢
    • 2018-10-27
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 2019-02-10
    相关资源
    最近更新 更多