如果结构浅拷贝,如何强制编译器错误?

我维护一个库,其中导出的结构具有不应浅拷贝的字段。例如:

type Example struct {
    Val    int
    Nums   []int
}

作为Nums切片类型的字段,Foo实例的浅拷贝复制切片头并允许错误:

foo := Example{Val: 1, Nums: []int{100}}
bar := Example

bar.Nums[0] = 200

fmt.Println(foo.Nums) // [200]

我想防止代码导入库以浅拷贝结构。可能的解决方案:

  • 返回一个指针的构造函数,但无论如何都不能阻止客户端取消引用和浅拷贝:
pfoo := lib.NewFoo() // returns type `*Foo`
foo := *pfoo // now variable foo is type `Foo`
foo2 := foo  // I don't want this
  • 向库中添加丰富的文档以阻止浅拷贝。我也可以声明在我的库中的所有方法,其使用Foos到需要指针类型,使事情变得安全在我身边,但同样,进口商代码可能会改写函数使用Foo的值。
  • 添加一个Clone()方法到Foo,但这属于“文档”问题:人们可能不会阅读它。
  • 添加自定义检查,go vet但这不会导致编译器错误。
  • 重写库以避免暴露的不可复制字段
  • 忍受出现错误的可能性

但是,还有另一种方法可以强制编译器在结构浅拷贝上抛出错误吗?

回答

问题运行时:添加 NoCopy 文档结构类型?解决这个问题。对该问题
的评论推荐了此解决方案:

请注意,绝对必须选择加入 vet 检查的代码已经可以这样做了。一个包可以定义:

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
}

通过此更改,该go vet命令会打印assignment copies lock value to y:Example contains noCopy以下代码的警告:

var x Example
y := x

在操场上运行示例。

记录不应复制该值的要求。Clone()如果应用程序需要深拷贝,请提供一种方法。

该方法不会增加 的大小,Example因为 a 的大小 struct{}为零。

标准库sync.WaitGroup类型使用 这种方法。


以上是如果结构浅拷贝,如何强制编译器错误?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>