结构体和 GoRoutines,切换实例?
Posted
技术标签:
【中文标题】结构体和 GoRoutines,切换实例?【英文标题】:Structs and GoRoutines, switches instances? 【发布时间】:2021-12-04 07:35:19 【问题描述】:我有这个功能:
func New(config *WatcherConfig) *Watcher
instance := &Watcher
config: config,
connections: make(map[string]ConnectionInfo),
lock: sync.Mutex,
go instance.Start()
return instance
它创建了一个Watcher
的新实例,目前有两个WatcherConfig
。如您所见,我使用 Go 例程启动了另一个名为 Start()
的函数。
func (w *Watcher) Start()
fmt.Println(w.config.PathToLogFile)
一个WatcherConfig
对于PathToLogFile
的值为/var/log/open***.log
,另一个WatcherConfig
对于PathToLogFile
的值为/var/log/postfix.log
。但是,当我使用 GoRoutine 调用 Start()
函数时,它会打印两次 /var/log/postfix.log
。如果我删除 go 例程,就像这样:
func New(config *WatcherConfig) *Watcher
instance := &Watcher
config: config,
connections: make(map[string]ConnectionInfo),
lock: sync.Mutex,
instance.Start()
return instance
它现在可以正确打印/var/log/open***.log
和/var/log/postfix.log
。
调用New()
的代码
/// ---------
/// Parse config file
/// ---------
configuration, err := config.ParseConfig(*configFileLocation)
if err != nil
log.Fatalln(err)
var watchers []*watcher.Watcher
for _, watcherConfig := range configuration.Watchers
watchers = append(watchers, watcher.New(&watcherConfig))
为什么 go 例程“切换”到另一个实例?
【问题讨论】:
【参考方案1】:如何解决:
for _, watcherConfig := range configuration.Watchers
watcherConfig := watcherConfig // copy
watchers = append(watchers, watcher.New(&watcherConfig))
Go 中的范围循环重用迭代变量,即它们重用分配的内存以减少分配,在您的情况下它是 watcherConfig
变量。因此,您使用New(&watcherConfig)
传递给New
的指针将指向相同的内存(因为它被重复使用)。因此,所有观察者最终都会得到相同的配置。
New
中没有 goroutine 的版本只有 看起来正常工作,因为 print 语句输出当前存储在共享内存中的值,但是一旦循环结束,观察者仍然会, 有一个相同的,最后一个,配置的参考。
FAQ entry 讨论了这个问题。
【讨论】:
我永远不会想到这一点:) 谢谢。 @TonyP。请记住,仅如果您正在获取迭代变量的地址,或者在迭代完成后执行的闭包中引用它,则会出现此问题:@987654322 @以上是关于结构体和 GoRoutines,切换实例?的主要内容,如果未能解决你的问题,请参考以下文章