如何在Go结构体中初始化成员

huangapple go评论134阅读模式
英文:

How to initialize members in Go struct

问题

我是新手,对Golang中的分配使我发疯:

  1. import "sync"
  2. type SyncMap struct {
  3. lock *sync.RWMutex
  4. hm map[string]string
  5. }
  6. func (m *SyncMap) Put (k, v string) {
  7. m.lock.Lock()
  8. defer m.lock.Unlock()
  9. m.hm[k] = v, true
  10. }

然后,我只是调用:

  1. sm := new(SyncMap)
  2. sm.Put("Test", "Test")

此时我会得到一个空指针恐慌。

我通过使用另一个函数来解决这个问题,并在new()之后立即调用它:

  1. func (m *SyncMap) Init() {
  2. m.hm = make(map[string]string)
  3. m.lock = new(sync.RWMutex)
  4. }

但我想知道是否有可能摆脱这个样板初始化的方式?

英文:

I am new to Golang so allocation in it makes me insane:

  1. import "sync"
  2. type SyncMap struct {
  3. lock *sync.RWMutex
  4. hm map[string]string
  5. }
  6. func (m *SyncMap) Put (k, v string) {
  7. m.lock.Lock()
  8. defer m.lock.Unlock()
  9. m.hm[k] = v, true
  10. }

and later, I just call:

  1. sm := new(SyncMap)
  2. sm.Put("Test, "Test")

At this moment I get a nil pointer panic.

I've worked around it by using another one function, and calling it right after new():

  1. func (m *SyncMap) Init() {
  2. m.hm = make(map[string]string)
  3. m.lock = new(sync.RWMutex)
  4. }

But I wonder, if it's possible to get rid of this boilerplate initializing?

答案1

得分: 70

你只需要一个构造函数。一个常用的模式是

  1. func NewSyncMap() *SyncMap {
  2. return &SyncMap{hm: make(map[string]string)}
  3. }

如果你的结构体内有更多的字段,可以在这个构造函数中启动一个goroutine作为后台,或者注册一个finalizer来完成所有操作。

  1. func NewSyncMap() *SyncMap {
  2. sm := SyncMap{
  3. hm: make(map[string]string),
  4. foo: "Bar",
  5. }
  6. runtime.SetFinalizer(sm, (*SyncMap).stop)
  7. go sm.backend()
  8. return &sm
  9. }
英文:

You just need a constructor. A common used pattern is

  1. func NewSyncMap() *SyncMap {
  2. return &SyncMap{hm: make(map[string]string)}
  3. }

In case of more fields inside your struct, starting a goroutine as backend, or registering a finalizer everything could be done in this constructor.

  1. func NewSyncMap() *SyncMap {
  2. sm := SyncMap{
  3. hm: make(map[string]string),
  4. foo: "Bar",
  5. }
  6. runtime.SetFinalizer(sm, (*SyncMap).stop)
  7. go sm.backend()
  8. return &sm
  9. }

答案2

得分: 11

'Mue'的解决方案不起作用,因为互斥锁没有初始化。以下修改后的代码可以正常工作:

  1. package main
  2. import "sync"
  3. type SyncMap struct {
  4. lock *sync.RWMutex
  5. hm map[string]string
  6. }
  7. func NewSyncMap() *SyncMap {
  8. return &SyncMap{lock: new(sync.RWMutex), hm: make(map[string]string)}
  9. }
  10. func (m *SyncMap) Put (k, v string) {
  11. m.lock.Lock()
  12. defer m.lock.Unlock()
  13. m.hm[k] = v
  14. }
  15. func main() {
  16. sm := NewSyncMap()
  17. sm.Put("Test", "Test")
  18. }

http://play.golang.org/p/n-jQKWtEy5

英文:

The solution of 'Mue' doesn't work since the mutex is not initialized. The following modification works:

  1. package main
  2. import "sync"
  3. type SyncMap struct {
  4. lock *sync.RWMutex
  5. hm map[string]string
  6. }
  7. func NewSyncMap() *SyncMap {
  8. return &SyncMap{lock: new(sync.RWMutex), hm: make(map[string]string)}
  9. }
  10. func (m *SyncMap) Put (k, v string) {
  11. m.lock.Lock()
  12. defer m.lock.Unlock()
  13. m.hm[k] = v
  14. }
  15. func main() {
  16. sm := NewSyncMap()
  17. sm.Put("Test", "Test")
  18. }

http://play.golang.org/p/n-jQKWtEy5

答案3

得分: 5

好的,以下是翻译好的内容:

deamon的发现很好。Mue可能在考虑将锁作为值而不是指针的更常见的模式。由于Mutex的零值是一个可立即使用的未锁定的Mutex,它不需要初始化,并且将其作为值包含是常见的。进一步简化,您可以通过省略字段名来嵌入它。然后,您的结构体将获得Mutex的方法集。请参见此工作示例,http://play.golang.org/p/faO9six-Qx。此外,我去掉了对defer的使用。在某种程度上,这是一种偏好和编码风格的问题,但由于它确实有一些小的开销,我倾向于在小函数中不使用它,特别是如果没有条件代码。

英文:

Good catch by deamon. Mue was possibly thinking of the more common pattern of including the lock as a value rather than a pointer. Since the zero value of a Mutex is a ready-to-use unlocked Mutex, it requires no initialization and including one as a value is common. As a further simplification, you can embed it by omitting the field name. Your struct then acquires the method set of the Mutex. See this working example, http://play.golang.org/p/faO9six-Qx. Also I took out the use of defer. To some extent it's a matter of preference and coding style, but since it does have a small overhead, I tend not to use it in small functions, especially if there is no conditional code.

huangapple
  • 本文由 发表于 2010年12月21日 19:58:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/4498998.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定