在泛型函数中,如何按值复制具有泛型类型的参数?
下面是一个简单的例子:
type MyInterface interface { // Interface use for type constraint
SetID(string)
}
type Implem struct { // Implements MyInterface
ID string
}
func (i *Implem) SetID(id string) {
i.ID = id
}
func doStuff[T MyInterface](input T) T {
res := input // Here I want to make a copy of input, so the next line modify res but not input
res.SetID("newID")
return res
}
func main() {
implem := &Implem{ID: "oldID"}
res := doStuff(implem)
fmt.Println(implem) // Should be "oldID"
fmt.Println(res) // Should be "newID"
}
我尝试了几种方法,比如将res
声明为*T
并将input设置为它的值,或者使用类型Assert,但SetID
仍然修改input。
按值复制input
的最佳方法是什么?
1条答案
按热度按时间eimct9ow1#
在一般情况下,浅层复制类型参数的工作方式与用于示例化它的任何类型参数相同。如果您使用非指针类型示例化
T
,则赋值将复制其值。如果您使用指针类型示例化T
,则赋值仍将复制其值,但该值是内存地址。在您编写的代码中,类型约束
MyInterface
可以由指针和非指针类型满足。假设,你可以声明一个类型如下:
对值接收者的字段的任何赋值都是无效的,但
Foo
将是有效的类型参数。也许你想做的是将类型参数限制为指针类型。这样你就可以捕获基类型并解引用以浅复制值。
这个输出
Playground:https://go.dev/play/p/U8Ssq3_YPVi
作为替代方案,您可以向结构体添加一个额外的方法,以返回它的副本。然后在泛型函数中,您可以向具有该方法的匿名接口键入assert:
Playground:https://go.dev/play/p/K7MOApHdEmM
在我看来,使用匿名接口更方便,可读性更强,因为类型参数
T
是以一种不言自明的方式使用的。当然,你可以定义一个命名接口:并对使用
T
示例化的接口Assert:Playground:https://go.dev/play/p/Berisu6Qz-P