调用Go包中的全局变量

时间:2017-11-05 21:00:03

标签: go

我有兴趣使用一个使用全局变量的Go包,对于我的应用程序来说,这是一个关键的"变量"。每次我调用这个包时,我想设置该变量(它被导出)。我从各种Go例程中调用它。有没有推荐的策略来排序/同步我对该包的调用,以便我的代码不会在该全局变量上发生冲突?

以下是一个例子:

package main

import (
    "fmt"
    "sync"
    "time"

    "github.com/jameshaskell/_sketches/globalvars/testlib"
)

var wg sync.WaitGroup

func gr(i int) {
    defer wg.Done()
    testlib.GlobalVar = i
    duration := time.Duration(i) * time.Millisecond
    time.Sleep(duration)
    fmt.Printf("   pause %d DONE\n", i)
    fmt.Printf("      global var: %d should be: %d  TestFunc: %s\n", testlib.GlobalVar, i, testlib.TestFunc())
}

func main() {
    for i := 0; i <= 10; i += 1 {
        wg.Add(1)
        go gr(i)
    }
    wg.Wait()
}

我试图访问的软件包就像:

package testlib

import "fmt"

var GlobalVar int

func TestFunc() string {
    return fmt.Sprintf("GlobalVar: %d\n", GlobalVar)
}

注意:我希望使用的包(具有全局变量)不是我的...

3 个答案:

答案 0 :(得分:1)

你可以使用atomic包,但要注意那里的警告:

  

这些功能需要非常小心才能正确使用。除了   特殊的低级应用程序,同步性更好   通道或同步包的设施。分享记忆   通信;不要通过共享记忆来沟通。

或者您可以使用sync.Mutex来保护变量,但这需要将其包装在结构或访问函数中以正确控制访问。

有一个更广泛的问题,你应该尝试回答 - 如果你每次访问包时都设置这个变量,为什么它是一个包变量?为什么不把它传递给需要它的函数呢?由于它每次都会发生变化,因此除了它所带来的同步问题外,封装变量几乎没有什么意义。

答案 1 :(得分:1)

这个变量是否打算以这种方式使用?可能有一些特定的二传手/吸气剂吗?文档是否有关于?

的一些信息

我认为代码变得非常脆弱,因为您无法控制对变量的所有访问。您可以使用互斥锁序列化代码中的访问权限。但另一个lib的代码不知道你的。此外,它可以在新版本或错误修复中突然改变。

所以我更喜欢:

  1. 在官方文档中阅读

  2. 如果文档允许,我无法避免使用它,请根据任务使用sync / mutex / atomic / channel保护对变量的访问。

  3. 使用变量

  4. 准备测试以涵盖不同的案例
  5. 运行竞争状态检测器作为CI测试的一部分。

答案 2 :(得分:0)

atomic包与Value类型

一起使用