在日常的项目开发过程中,都有 Nocpoy (不可复制)对象的需求,在golang怎么中实现这个特性呢?
在sync/cond.go中,有下面的实现。
// noCopy may be embedded into structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}
其实我们所使用的sync.WaitGroup内部就是包含了这样的一个nocopy的结构体,来实现不可复制
// A WaitGroup must not be copied after first use.
type WaitGroup struct {
noCopy noCopy
// 64-bit value: high 32 bits are counter, low 32 bits are waiter count.
// 64-bit atomic operations require 64-bit alignment, but 32-bit
// compilers do not ensure it. So we allocate 12 bytes and then use
// the aligned 8 bytes in them as state.
state1 [12]byte
sema uint32
}
注意:
1. 该noCopy并没有导出来,我们不可使用
2. 想要实现NoCopy,需要自己定义一个这样的结构体实现其Lock()接口即可,结构体名字随意
3. 即使包含了NoCopy的结构体,也不是真正的就不可复制了,实际上毫无影响,无论是编译,还是运行都毫不影响
4. 只有在go vet命令下,才会提示出其中的nocopy问题
5. vscode编译器中可以直接提示出来
提示效果如下(fmt中,t1复制给t2中,都有绿色波浪线标示):
示例代码的效果结果如下:
示例代码如下:
package main
import "fmt"
// 需先定义noCopySign的结构体,该结构体名字随意,关键是要定义下面的Lock()函数
type noCopySign struct{}
func (*noCopySign) Lock() {}
// 这里定义自己的结构体,包含上面的noCopySign结构体即可
type nocopyTest struct {
nocopy noCopySign
a int32
}
func main() {
/// 错误做法 ///
t1 := nocopyTest{}
t1.a = 111
fmt.Printf("t1:%v \n", t1)
t2 := t1
t2.a = 222
fmt.Printf("t1:%v,t2:%v \n", t1, t2)
/// 正确做法 ///
t3 := &nocopyTest{} // 一定要使用指针
t3.a = 333
fmt.Printf("t3:%v \n", t3)
t4 := t3 // t4指向t3所指向的对象,所以是同一个对象
t4.a = 444
fmt.Printf("t3:%v,t4:%v \n", t3, t4)
}