【发布时间】:2014-04-08 21:04:08
【问题描述】:
我有一个函数,它接受一个接口并返回一个接口。它想将结果初始化为源的副本,然后进行一些更改,然后返回结果。例如:
type Something interface {
CopySomething() Something // I'd like to get rid of this
SetX(x int)
}
type RealThing struct {
x int
}
func (t *RealThing) SetX(x int) {
t.x = x
}
func (t *RealThing) CopySomething() Something {
newT := *t
return &newT
}
func Updated(original Something, newX int) Something {
newThing := original.CopySomething() // I'd like to make the copy without .CopySomething()
newThing.SetX(newX)
return newThing
}
func main() {
a := &RealThing{x: 1}
b := Updated(a, 5)
fmt.Printf("a = %v\n", a)
fmt.Printf("b = %v\n", b)
}
这行得通,但CopySomething() 方法似乎没有必要(对于每个需要复制内容的接口,我都需要另一种相同的方法)。有没有更好的方法在没有额外方法的情况下在Updated() 内复制original?有没有更惯用的方法来实现这一点?
在我正在处理的特定情况下,我可以只实例化一个与original 相同类型的新实例(我真的不需要副本)。这样问题会更简单吗?
根据 Evan 的评论,我想我会提供一些我已经尝试过的其他基于反射的东西:
newThing := reflect.New(reflect.TypeOf(original))
==> 编译错误:类型 reflect.Value 没有字段或方法 SetX
newThing := reflect.New(reflect.TypeOf(original)).Interface().(Something)
===> 运行时错误:接口转换:**main.RealThing is not main.Something
newThing := reflect.Indirect(reflect.New(reflect.TypeOf(original))).Interface().(Something)
===> 运行时错误:无效的内存地址或 nil 指针取消引用
此时,我觉得我的反射变得很傻,并停止了对它的打击。
【问题讨论】:
-
有没有办法将其重构为不使用指针?然后你会自动在界面中得到一个浅拷贝。
-
我不明白。你怎么会不使用指针,但仍然实现 SetX?
-
啊,没关系。我很着急,没有考虑清楚。您必须在结构内使 X 成为指针,并且可能会使它更加复杂。
标签: go