Gas*_*onQ 1 struct go shallow-copy
我维护一个库,其中导出的结构具有不应浅拷贝的字段。例如:
type Example struct {
Val int
Nums []int
}
Run Code Online (Sandbox Code Playgroud)
作为Nums切片类型的字段,Foo实例的浅拷贝复制切片头并允许错误:
foo := Example{Val: 1, Nums: []int{100}}
bar := Example
bar.Nums[0] = 200
fmt.Println(foo.Nums) // [200]
Run Code Online (Sandbox Code Playgroud)
我想防止代码导入库以浅拷贝结构。可能的解决方案:
pfoo := lib.NewFoo() // returns type `*Foo`
foo := *pfoo // now variable foo is type `Foo`
foo2 := foo // I don't want this
Run Code Online (Sandbox Code Playgroud)
Foos到需要指针类型,使事情变得安全在我身边,但同样,进口商代码可能会改写函数使用Foo的值。Clone()方法到Foo,但这属于“文档”问题:人们可能不会阅读它。go vet但这不会导致编译器错误。但是,还有另一种方法可以强制编译器在结构浅拷贝上抛出错误吗?
问题运行时:添加 NoCopy 文档结构类型?解决这个问题。对该问题
的评论推荐了此解决方案:
请注意,绝对必须选择加入 vet 检查的代码已经可以这样做了。一个包可以定义:
Run Code Online (Sandbox Code Playgroud)type noCopy struct{} func (*noCopy) Lock() {}然后将 noCopy noCopy 放入任何必须由 vet 标记的结构中。
还需要 Unlock 方法来触发警告。这是示例的完整解决方案:
type noCopy struct{}
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}
type Example struct {
noCopy noCopy
Val int
Nums []int
}
Run Code Online (Sandbox Code Playgroud)
通过此更改,该go vet命令会打印assignment copies lock value to y:Example contains noCopy以下代码的警告:
var x Example
y := x
Run Code Online (Sandbox Code Playgroud)
记录不应复制该值的要求。Clone()如果应用程序需要深拷贝,请提供一种方法。
该方法不会增加 的大小,Example因为 a 的大小 struct{}为零。