【问题标题】:Global variable private to file文件专用的全局变量
【发布时间】:2017-07-22 11:18:47
【问题描述】:

在 GOLANG 中,有没有办法使变量的范围对包内的文件是本地的? 就我而言,有 2 个文件 ex1.go 和 ex02.go。 ex01.go 定义了一个全局变量

var wg sync.WaitGroup

在该文件中的函数中使用。

在另一个文件 ex02.go 中(除了 ex01.go 和 ex02.go 都属于同一类问题 - 即并发之外,它与 ex01.go 没有关系),我无法将 waitGroup 的变量定义为

var wg sync.WaitGroup

我收到一个错误 - “变量名在此块中重新声明”

有没有办法防止变量名溢出到其他文件?

【问题讨论】:

    标签: go global-variables


    【解决方案1】:

    出于变量作用域的目的,文件在 Go 中没有意义。将包中的所有文件视为将它们连接起来,这(简化)正是在编译之前发生的事情。

    这意味着:不,没有办法将变量范围限定为文件。

    如果你需要两个全局的WaitGroups,你需要将它们定义为单独的变量。

    【讨论】:

    • 谢谢马库斯,这似乎很不方便......或者可能只是我。没有什么相当于闭包的东西(我们在javascript中定义的方式:(function(){})()..可以定义吗?如果有一个大型项目,如何跟踪包中的变量?跨度>
    • 实现这一点的最佳方法是不使用全局变量。在函数中声明变量并将其传递给使用它的函数。我不会将此作为自己的答案发布,因为在您的问题范围内,Markus 是正确的,即无法在整个包之间共享全局变量。
    • 感谢 Verran(和 Markus)。这是测试项目中只有一个变量的情况。如果将“控制变量”传递给这样的函数,它会不会使函数“不干净”,因为我想象一个函数只是为了处理数据而“控制代码”会处理控制语义.你不同意吗? :) 无论如何.. 感谢您的投入!
    • @devak23 这在很大程度上取决于您的代码。对于初学者,我觉得将等待组作为全局变量放在首位很奇怪。但是没有你的代码,很难说该怎么做。也许您可以将其发布在codereview.stackexchange.com 上,我们可以了解该怎么做。但听起来你会更喜欢pipeline 或简单的频道
    【解决方案2】:

    只有显式导入的标识符才有文件的作用域。在文件 wg.go 中说你定义

    package wg
    var Wg sync.WaitGroup
    // and all staff common to class of problems - i.e. concurrency
    

    然后你可以在文件 ex1.go 中

    import wg
    wg.Wg.Add(1) //use locally to file
    

    ex2.go 中相同

    【讨论】:

      【解决方案3】:

      我建议您参考以下信息并将其适当地应用于您的具体问题。以下大部分示例来自This Medium article

      Go 的变量声明和作用域有几个特征与其他语言一致,有些特征更适合 Go。

      更一致的特征处理块和变量声明。如果您在一个块中声明一个变量v,那么嵌套到此的每个块都可以“看到”v。如果您在其中一个嵌套块中重新声明 a ,那么当您离开这个内部块时,您会将该值丢失给 a 并重新获得旧值。

      例子:

      func main() {
          {
              v := 1
              {
                  fmt.Println(v)
              }
              fmt.Println(v)
          }
          // “undefined: v” compilation error
          // fmt.Println(v)
      }
      
      > ./bin/sandbox
      1
      1
      

      在这个 ^ 示例中,您可以看到变量的值在其声明嵌套的范围内“可见”

      v := 1
      {
          v = 2  // assignment
          fmt.Println(v)
      }
      fmt.Println(v)
      
      >./bin/sandbox
      2
      2
      

      此示例对此进行了扩展,说由于变量v 是在外部范围内声明的,那么我也可以重新分配而不是重新声明v 的值,并让它在任何可以“看到”的范围内生效'v.

      v := 1
      {
          v := 2  // short variable declaration
          fmt.Println(v)
      }
      fmt.Println(v)
      
      >./bin/sandbox
      2
      1
      

      最后一个示例更接近您的原始问题。这表明我可以有相同的变量名,但根据我的范围有多个带有多个变量的声明。这让我们更加与众不同

      更多不同的特性涉及 Go 的包私有和公共声明以及顶级标识的概念。

      首先让我们谈谈顶级识别。顶级标识是在任何其他类型或函数声明之外声明变量、类型或函数。 func main() 是顶级标识的一个很好的例子。现在让我们考虑一个 Go 包中的多个文件。考虑 Go 包中的多个文件的一种方法是将它们全部附加在一起以形成一个非常长的文件。考虑到这一点,我们现在可以看到为什么没有文件私有变量的概念。只有包私有或包公共。

      包私有是顶级变量,仅对包本身可见,对可能导入此包的任何人可见。包 public 对整个包任何可能导入此包的人都是可见的。这仅通过名称的第一个字母的大写来描述。

      // Package Public
      func Main(){...}
      var MyVar;
      type MyType uint64;
      
      // Package Private
      func main(){...}
      var myVar;
      type myType uint64;
      

      请注意,大小写确实很重要,main()Main() 确实调用相同的函数。您也可以使用它来解决您的问题,但我不建议仅仅为了绕过重新声明而更改大小写。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-13
        相关资源
        最近更新 更多