在 Go 中,我们可以使用:
type Data struct {
lock *sync.Mutex
}
Run Code Online (Sandbox Code Playgroud)
或者
type Data struct {
lock sync.Mutex
}
Run Code Online (Sandbox Code Playgroud)
并且,像这样使用:
func (d *Data) Update() {
d.lock.Lock()
defer d.lock.Unlock()
// update
}
Run Code Online (Sandbox Code Playgroud)
我能想到的区别是只*sync.Mutex需要实例化即可使用。
是什么区别sync.Mutex和*sync.Mutex围棋,哪一个更好?
Leo*_*nes 13
mkopriva 的评论是正确的,可能应该是公认的答案。
然而,阅读OP的问题,我认为可能存在一个值得扩展的潜在误解:OP提到唯一的区别是“一个必须初始化,另一个则不需要”。
指向T和 的指针之前的根本区别T意味着使用变量时会发生一系列行为变化,其中只有一个是其实例化。
首先:这两种情况都存在实际实例化。在这种T情况下,它是隐含在声明中的,因为变量包含实例本身(可以这么说)。但在指针的情况下,它可能发生在代码中完全不同的位置,因为变量仅包含对实例的间接访问。除其他外,这解释了为什么只有指针变体才能导致“零指针取消引用”:只有在这种情况下,您的代码才能在变量实际初始化之前尝试对变量执行任何操作。
其次:使用具体T以及 go 是一种“按值传递”语言这一事实,意味着每次调用都会复制任何具体的函数参数(或方法接收者)。
这至少会在三个方面产生影响:
struct,并且调用发生在应用程序的热路径中,则您将复制大量数据。struct|,这些副本可能会对您的应用程序的内存占用产生影响。最后,这将我们引向具体的情况sync.Mutex:查看上面的要点和代码,我们可以看到性能和内存使用通常不是问题,因为sync.Mutex是一个非常小的struct.
然而,最后一点非常重要:指向 a 的指针意味着什么sync.Mutex?这意味着包含的副本struct将指向同一个锁。即:这意味着您的两个实例struct可能共享一个锁。
由于go vet不会抱怨复制指向互斥体的指针,因此复制父级struct不会引起警钟,并且您最终可能会使用同一锁保护两个单独的实例,从而可能导致死锁。
总之:除非您知道您想使用同一锁保护某些内容的不同副本(恕我直言,不太可能),否则最好使用具体的sync.Mutex|es。
如果创建指针的唯一原因sync.Mutex是告诉您不要复制它,那么您可能应该考虑在您试图保护的对象 go vet上查找一层:很可能您通过使用像这样的具体接收器无意中复制了它struct
func (t T) foo(){...}
Run Code Online (Sandbox Code Playgroud)
你应该在哪里
func (t *T) foo(){...}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5282 次 |
| 最近记录: |