【问题标题】:Structs and GoRoutines, switches instances?结构体和 GoRoutines,切换实例?
【发布时间】: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/openvpn.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/openvpn.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 例程“切换”到另一个实例?

【问题讨论】:

    标签: go struct goroutine


    【解决方案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 @
    猜你喜欢
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-11
    • 2018-06-15
    • 1970-01-01
    • 2020-09-12
    相关资源
    最近更新 更多