Go 中可别用复制锁,会有这些大问题!

assignment copies lock value to val

assignment copies lock 错误

当我们用 go vet 检查静态问题的时候,你是否遇到 noCopy 相关的错误。最典型的就是 lock 的变量,测试代码:

静态检查的时候报错:

遇到这种语法提示可不能大意,一定要解决。以免给以后埋坑。那童鞋是否想过,为什么锁不能拷贝?

为什么锁不能拷贝?

很多时候我们被直接告诉了答案,Mutex 锁不能拷贝。但是原因呢?

划重点:变量资源本身带状态且操作要配套的不能拷贝。

比如说 Mutex 锁,WaitGroup ,这些本身都是带状态的信息的。并且它们操作一定要配套,不然就会死锁。什么意思?

锁的配套:

WaitGroup 的配套:

这种一定要严格的匹配,一次加锁对应一次解锁,数量不对就会出问题。

回到问题本身,为什么锁不能拷贝?

因为拷贝了很容易会导致操作次数不匹配。很容易理解,拷贝就是创建了一个新的变量,旧的变量加了锁,新的变量解锁。牛头不对马嘴,岂不就死锁了。就算不死锁也可能达不到锁互斥的目的。看个简单的例子:

上面就死锁了。有童鞋可能会反驳,我怎么可能犯这种低级错误。那再来一个:

这种运行起来也是报错的,因为锁变量的拷贝导致加锁解锁不是配套的操作。

再举个例子,看一个 WaitGroup 很典型的死锁问题:

上面的 wg 使用也会导致死锁。归根结底就是 WaitGroup 的变量操作没配套 。

划重点:针对需要配套操作的变量类型,基本上都会要求 noCopy 的,否则拷贝出来就乱套了。

在上万行的业务代码场景,可能你的问题更隐蔽。很悲伤的是,上面的三个例子都能正常编译。好消息是,上面三个例子都能用 go vet 检查出来。所以大家一定要善用 go vet 来配合检查,能够过滤大部分的低级问题。

Go 没有更好的办法阻止拷贝对象,于是通过了一个 noCopy 的机制。这个不能阻止编译,但是可以让 go vet 能再静态检查的时候检查出来。Go 里面通过实现一个 noCopy 的结构体,然后嵌入这个结构体就能让 go vet 检查出来。

类似于 Mutex,WaitGroup ,变量嵌入了这个 noCopy 的类型,就能被 go vet 检查出来。

通常业务如果也有不让拷贝的需求,会怎么做呢?

最简单的是:嵌入 sync.Mutex 变量。就能让这个变量也具有 noCopy 的功能。

哪些类型不能拷贝?

比如 Mutex Lock,Cond,Pool,WaitGroup 。这些资源都严格要求操作要配套:

不配套的操作,就会出问题。

类似于 Mutex Lock,WaitGroup 等资源一定要 操作配套 ,加锁一定对应解锁。否则牛头不对马嘴就一定会出问题;

“拷贝” 就是出现这种不一致的源头之一。所以 noCopy 就是解决这个问题的方案;

Go 没有更好的办法阻止你 Copy,没法在编译的时候阻止。但提供了 noCopy 机制,让程序员可以在 go vet 检查出来;

go vet 检查出的问题一定要慎重,一个不漏的解决它们;

点赞、在看  是对作者最大的支持。

扫码关注公众号「网管叨bi叨」

给网管个星标,第一时间吸我的知识 👆

网管整理了一本《Go 开发参考书》收集了70多条开发实践。去公众号回复【gocookbook】领取!还有一本《k8s 入门实践》讲解了常用软件在K8s上的部署过程,公众号回复【k8s】即可领取!

觉得有用就点个在看  👇👇👇

assignment copies lock value to val

“相关推荐”对你有帮助么?

assignment copies lock value to val

请填写红包祝福语或标题

assignment copies lock value to val

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

assignment copies lock value to val

Go – How to get around assignment copies lock value to tr: net/http.Transport contains sync.Mutex

go http mutex ssl

When I run go vet the following error is output:

client.go:2345:

How can I get around this warning? It's not stopping my builds; but, it's a warning and I don't want warnings.

Best Answer

You should be creating a *http.Transport pointer, instead of a value

Related Solutions

How to get .pem file from .key and .crt files.

Your keys may already be in PEM format, but just named with .crt or .key.

If the file's content begins with -----BEGIN and you can read it in a text editor:

The file uses base64, which is readable in ASCII, not binary format. The certificate is already in PEM format. Just change the extension to .pem.

If the file is in binary:

For the server.crt, you would use

For server.key, use openssl rsa in place of openssl x509 .

The server.key is likely your private key, and the .crt file is the returned, signed, x509 certificate.

If this is for a Web server and you cannot specify loading a separate private and public key:

You may need to concatenate the two files. For this use:

I would recommend naming files with "includesprivatekey" to help you manage the permissions you keep with this file.

Go – How to check if a map contains a key in Go

One line answer:

Explanation:

if statements in Go can include both a condition and an initialization statement. The example above uses both:

initializes two variables - val will receive either the value of "foo" from the map or a "zero value" (in this case the empty string) and ok will receive a bool that will be set to true if "foo" was actually present in the map

evaluates ok , which will be true if "foo" was in the map

If "foo" is indeed present in the map, the body of the if statement will be executed and val will be local to that scope.

Related Topic

  • Go – How to convert an int value to string in Go
  • Go – How to set headers in http get request
  • Go – How to get the directory of the currently running file
  • Go – How to get the last element of a slice

assignment copies lock value to val

Beware of copying mutexes in Go

Suppose we have a struct that contains a map, and we want to modify the map in a method. Here's a simple example :

A Container holds a map of counters, keyed by name. Its inc method increments the specified counter (let's assume that the counter already exists). main calls inc many times in a loop.

If we run this snippet, it will print out:

Now say that we want two goroutines to call inc concurrently. Since we are wary of race conditions, we'll use a Mutex to lock around the critical region:

What would you expect the output to be? I get something like this:

We were careful to use a mutex, so what went wrong? Can you see how to fix it? Hint: it's a single-character code change!

The problem with the code is that whenever inc is called, our container c is copied into it, because inc is defined on Container , not *Container ; in other words, it's a value receiver , not a pointer receiver . Therefore, inc can't really modify the contents of c per se.

But wait, how did the original sample work then? In the single-goroutine sample, we passed c by value too, but it worked - main observed the changes to the map done by inc . This is because maps are special - they are reference types, not value types. What's stored in Container is not the actual map data, but a pointer to it. So even when we create a copy of the Container , its counters member still contains the address of the same data.

So the original code sample is wrong too. Even though it works, it goes against the guidelines ; methods that modify the object should be defined on pointers, not values. Using a map here leads us to a false sense of security. As an exercise, try to replace the map with just a single int counter in the original example, and notice how inc increments a copy of it, so that in main its effects will not be seen.

The Mutex is a value type (see definition in Go's source , including the comment that explicitly asks not to copy mutexes), so copying it is wrong. We're just creating a different mutex, so obviously the exclusion no longer works.

The one-character fix is, therefore, to add a * in front of Container in the definition of inc :

Then c is passed by pointer into the method, and actually refers to the same instance of Container in memory as the one the caller has.

This is not an uncommon problem! In fact, go vet will warn about it:

It often comes up in scenarios like HTTP handlers, which are invoked concurrently without the programmer's explicitly writing any go statements. I'll write more about this in a future post.

This issue really helps clarify the difference between value and pointer receivers in Go, in my opinion. To drive the point home, here's another code sample, unrelated to the last two. It leverages Go's ability to create pointers to objects using & and examine their addresses with the %p formatting directive:

Its output is (in one particular run on my machine - for you the addresses may be different, though the relations between them should be the same):

The main function creates a Container and prints out its address and the address of field s . It then invokes two Container methods.

byValMethod has a value receiver, and it prints out different addresses because it gets a copy of c . On the other hand, byPtrMethod has a pointer receiver and the addresses it observes are identical to the ones in main , because it takes the address of the actual c when invoked, not a copy.

For comments, please send me an email .

assignment copies lock value to val

How should I avoid - literal copies lock value from

Kasun Vithanage's profile photo

Kasun Vithanage

Dave Cheney's profile photo

Dave Cheney

jake...@gmail.com's profile photo

[email protected]

This package is not in the latest version of its module.

Documentation ¶

Package pragma provides types that can be embedded into a struct to statically enforce or prevent certain language properties. The key observation and some code (shr) is borrowed from https://github.com/protocolbuffers/protobuf-go/blob/v1.25.0/internal/pragma/pragma.go

  • type CopyChecker
  • func (c *CopyChecker) Check()
  • func (c *CopyChecker) Copied() bool
  • type DoNotCompare
  • type DoNotCopy
  • type DoNotImplement
  • type NoUnkeyedLiterals
  • CopyChecker
  • DoNotCompare
  • DoNotImplement
  • NoUnkeyedLiterals

Constants ¶

This section is empty.

Variables ¶

Functions ¶, type copychecker ¶.

CopyChecker holds back pointer to itself to detect object copying. Deprecated. use DoNotCopy instead, check by go vet. methods Copied or Check return not copied if none of methods Copied or Check have bee called before

func (*CopyChecker) Check ¶

Check panic is c is copied

func (*CopyChecker) Copied ¶

Copied returns true if this object is copied

type DoNotCompare ¶

DoNotCompare can be embedded in a struct to prevent comparability.

type DoNotCopy ¶

DoNotCopy can be embedded in a struct to help prevent shallow copies. This does not rely on a Go language feature, but rather a special case within the vet checker.

See https://golang.org/issues/8005 .

type DoNotImplement ¶

Type nounkeyedliterals ¶.

NoUnkeyedLiterals can be embedded in a struct to prevent unkeyed literals.

Source Files ¶

Keyboard shortcuts.

IMAGES

  1. 7 Steps to Lock Formulas in Excel (Step-By-Step Guide)

    assignment copies lock value to val

  2. Solved The assignment is to load the value of variable X

    assignment copies lock value to val

  3. 7 Steps to Lock Formulas in Excel (Step-By-Step Guide)

    assignment copies lock value to val

  4. How to drag or copy formula and lock the cell value in Excel?

    assignment copies lock value to val

  5. 7 Steps to Lock Formulas in Excel (Step-By-Step Guide)

    assignment copies lock value to val

  6. How to Lock in a Cell Value in MS Excel : MS Excel Tips

    assignment copies lock value to val

VIDEO

  1. gen:LOCK

  2. Gear Lock Se Increase or Decrease Hone Wali Pencil Case #filling #stationery #backtoschool #unboxing

  3. Slide Pencil Lock Wali Authentic Geometry Box #stationery #schoolsupplies #filling #pencilcase

  4. Password Lock Wali Pencil Case, Cute Pencil Box, Geometry Box #filling #stationery #unboxing #shorts

  5. Locking assignments

  6. Padre Adam Kotas🔔Cristo no es una religión es una relación! Pasa de la religión a relación con Dios

COMMENTS

  1. How to get around assignment copies lock value to tr: net/http

    @Nilesh, there are lots of valid statements which are not logical. Unfortunately you can't readily see the mutex field from the docs, so this may not be obvious at first glance, but because the Transport type has all pointer receivers, should always be reused, and is safe for concurrent access, it's very unlikely that someone would choose a non-pointer value.

  2. Go 中可别用复制锁,会有这些大问题!-CSDN博客

    Go 没有更好的办法阻止拷贝对象,于是通过了一个 noCopy 的机制。. 这个不能阻止编译,但是可以让 go vet 能再静态检查的时候检查出来。. Go 里面通过实现一个 noCopy 的结构体,然后嵌入这个结构体就能让 go vet 检查出来。. type noCopy struct {} // Lock is a no-op used by ...

  3. Go Programming: Preventing Unintended Structure Copies with ...

    assignment copies lock value to wg2: sync.WaitGroup contains sync.noCopy ... // checkCopyLocksAssign checks if an assignment operation copies a lock func checkCopyLocksAssign(pass *analysis.Pass ...

  4. Go

    One line answer: if val, ok := dict["foo"]; ok { //do something here } Explanation: if statements in Go can include both a condition and an initialization statement. The example above uses both: initializes two variables - val will receive either the value of "foo" from the map or a "zero value" (in this case the empty string) and ok will receive a bool that will be set to true if "foo" was ...

  5. cmd/vet: vet is reporting lock value copying because of a Lock method

    main.go:11: assignment copies lock value to b: main.A main.go:12: assignment copies lock value to _: main.A exit status 1 $ The text was updated successfully, but these errors were encountered: All reactions. Copy link Contributor. JayNakrani commented Dec 28, 2016. vet checks ...

  6. go vet : Assignment copies lock value #5758

    Grove Current behavior: go vet -copylocks ./... finds 1 issue: MessageLine of code assignment copies lock value to newTransport: net/http.Transport contains sync.Mut... I'm submitting a ... bug report Traffic Control components affected ... Grove Current behavior: go vet -copylocks ./... finds 1 issue: MessageLine of code assignment copies lock ...

  7. [Question] Dealing with return copies lock value

    There are two choices for putting a mutex into a struct when considering the restriction that a mutex cannot be copied: Have a sync.Mutex as a plain field (no * ), and ensure every reference to an instance of that struct is a pointer (or is on the local stack, a la var mu sync.Mutex ). Make it a *sync.Mutex and initialize it somewhere so that ...

  8. Beware of copying mutexes in Go

    The main function creates a Container and prints out its address and the address of field s.It then invokes two Container methods.. byValMethod has a value receiver, and it prints out different addresses because it gets a copy of c.On the other hand, byPtrMethod has a pointer receiver and the addresses it observes are identical to the ones in main, because it takes the address of the actual c ...

  9. Go: Vet Command Is More Powerful Than You Think

    func main() {var lock sync.Mutex l := lock l.Lock() l.Unlock()} from vet: main.go:9:7: assignment copies lock value to l: sync.Mutex A struct that uses a lock should be used by pointer in order to ...

  10. go/analysis/passes/copylock/copylock.go

    const Doc = `check for locks erroneously passed by value: Inadvertently copying a value containing a lock, such as sync.Mutex or: sync.WaitGroup, may cause both copies to malfunction. Generally such: values should be referred to through a pointer.` var Analyzer = &analysis.Analyzer{Name: "copylocks", Doc: Doc,

  11. go-vet: assignment copies lock value of tls.Config #254

    assignment copies lock value to conf: crypto/tls.Config contains sync.Once contains sync.Mutex. Here: go-nsq/conn.go. Line 390 in 61f49c0. conf = *tlsConf. Since the tls.Config is an option in the nsq.Config, you can't be certain it isn't already being used, and therefore synchronization of the Once/Mutex are lost in the copied value.

  12. How should I avoid

    It allows Set to be passed by value, which is nice. But if you keep the mutex as a non pointer, then y ou probably want to pass a slice of set pointers: func (set *Set) Diff(sets []*Set) *Set. This avoids copying the mutex when you create your slice, so the test line becomes: set1.Diff([]*Set{set2, set3}) Of course your original Diff code is ...

  13. Golang source #1

    the go vet warning us about "assignment copies lock value to wg2: sync.WaitGroup contains sync.noCopy", so we can't copy the value of the WaitGroup type. (Of course if the wg is a pointer which points to a value where the type is WaitGroup, we can say wg2 := wg, but it isn't mean we copy the value.)

  14. go bug sync.Map · Issue #32641 · golang/go · GitHub

    Map, a multi-threaded, secure Map officially provided by Go, because of the need for multi-threading. Because of the need, I use a two-dimensional sync. Map, that is, sync. Map will contain another pile of sync. Map, at this time, very strange things happened, sync.

  15. pragma package

    DoNotCopy can be embedded in a struct to help prevent shallow copies. This does not rely on a Go language feature, but rather a special case within the vet checker. ... Output: Assignment copies lock value to '_': type 'DoNotCopy' contains 'sync.Mutex' which is 'sync.Locker'

  16. Assignment via copy-and-swap vs two locks

    For example: std::vector<int> v1(5); std::vector<int> v2(4); ... v1 = v2; In the above example, if v1 keeps its capacity to do the assignment, then the assignment can be done with no heap allocation or deallocation. But if vector uses the swap idiom, then it does one allocation and one deallocation. I note that as far as thread safety goes ...

  17. cmd/vet: vet is reporting lock value copying on composite literal

    go vet is reporting "assignment copies lock value to r: hipache.hipacheRouter" in the last line. The type hipacheRouter indeed contains a lock: ... Generally, it is not allowed to copy a lock by value. It is however safe to copy a zero value lock by value, as a special case and the only one that does not lead to strange results. This is what ...

  18. cmd/vet: copylocks false positives · Issue #16227 · golang/go

    Types.NewStruct constructs a new struct and omits (implicitly zeros) the lock fields. I think we should consider rolling back the new checks for 1.7 and restoring them in 1.8 without these false positives. At least in the case of struct initialization, ignoring fields being initialized to the zero value will help.

  19. protoc-gen-go: new message struct structure prevents struct copying in

    In general, its not safe to shallow copy any struct type where you don't control the implementation since you have no guarantee that you aren't accidentally copying atomic variables and locks (which is exactly the case here).