Implement struct no copy in GoLang

English 简体中文 繁体中文 ภาษาไทย Tiếng Việt
Summary

GoLang lacks an intuitive mechanism to prevent struct copying, which can be problematic for types like global configurations that should maintain a single instance. A common pattern to address this involves embedding a special noCopy struct within any type not intended for copying. This noCopy struct, which implements the sync.Locker interface with no-op Lock() and Unlock() methods, enables the go vet tool to identify instances where the containing struct is copied by value. While go vet will report warnings for such copies, the code will still compile and run successfully, making this approach a valuable development-time check rather than a compile-time enforcement.

存在一些情况,GoLang 中的一些结构体不应被复制。例如,有时全局配置应该只有一个版本在整个应用程序中传递,而不应该被复制和修改。

在 GoLang 中,没有直观的解决方案来防止结构体的复制。但是仍然有一些方法可以用来帮助防止这种情况在开发代码时发生。技巧是定义一些实现sync.Locker接口的结构体,并将此结构体嵌入到任何不应被复制的结构体中

// noCopy 可以嵌入到必须在第一次使用后不被复制的结构体中。
//
// 详情请参见 https://golang.org/issues/8005#issuecomment-190753527
// 。
type noCopy struct{}

// Lock 是 `go vet` 中 -copylocks 检查器使用的空操作。
func (*noCopy) Lock() {}
func (*noCopy) UnLock() {}

下面是一个解释上述内容的示例代码片段。

package main

import (
	"fmt"
)

type noCopy struct{}

func (*noCopy) Lock()   {}
func (*noCopy) Unlock() {}

type Demo struct {
	noCopy noCopy
}

func Copy(d Demo) {
}

func main() {
	d := Demo{}
	fmt.Printf("%+v", d)

	Copy(d)

	fmt.Printf("%+v", d)
}

现在,如果您在 main.go 文件上运行go vet,您将看到一些错误,告诉您某些地方复制了结构体(Copy())。

> go vet main.go
# command-line-arguments
.\main.go:16: Copy 按值传递锁:main.Demo 包含 main.noCopy
.\main.go:21: fmt.Printf 的调用复制锁值:main.Demo 包含 main.noCopy
.\main.go:23: Copy 的调用复制锁值:main.Demo 包含 main.noCopy
.\main.go:25: fmt.Printf 的调用复制锁值:main.Demo 包含 main.noCopy

这里需要注意的一点是,上述方法不会告诉编译器编译失败。如果您继续编译并运行它,它仍然可以工作。这只是为go vet提供了另一个提示,通常我们在构建项目之前运行它来检查我们的源代码中可能存在的问题。

> go run main.go
{noCopy:{}}{noCopy:{}}

参考:

GO VET NOCOPY NO COPY

  RELATED

  COMMENTS

0

No comment for this article.