如何在Go语言中跨包共享变量

3

我已经编写了一款简单的 Go 应用程序,并将其格式化为多个包。

+main
+controllers
+handlers
+commons
+utils

我在主包中启动服务器并在启动时读取服务器特定参数。

我想使用那些参数,例如commons包中的DB属性。但是我不能将主包导入到commons中,因为commons是controllers和handlers的依赖项,而它们又是主包的依赖项。因此,这会导致循环导入。

我们应该如何处理这种情况?是否有可能在需要时只读取配置一次,并在需要时在commons包内引用它?提供示例会更好。


2
选择一个不会导入其他包的包,这样所有的包都可以导入它。将共享变量放入其中。main 包也可以访问它以存储在启动时读取的参数。 - icza
你可能不应该为一个单独的Go应用程序拥有那么多独立的包。多年来,Go社区一直在讨论这个问题,但对于二进制文件而言,最好只有一个主要的包main,并仅将其他明显需要在不同项目中重用的包分离出来。这里有一些关于这一点的进一步讨论。 - AndrewN
假设您遵循AndrewN的建议(KISS),并暂时避免额外的包结构,您能否只使用flag包从命令行读取参数?这似乎可以解决所描述的问题。据我所知,flag包可以从任何包中调用(Go不是可爱吗?),而不仅仅是main,因此如果关键参数必须在共享包中但不是main中,则可以从那里进行操作。 - gbulmer
或者,你能从环境变量 os.Environ() 中读取参数吗?同样,它们可以从任何包中读取。 - gbulmer
从flag或os.Environ()读取参数在我们有许多配置时不可扩展。我现在使用的是config.yaml,并使用viper来读取它们。 - Anuruddha
1个回答

1
你可以使用一个配置包,在需要使用配置变量时,将其发送到另一个不同的包中的结构体中。
main() {
    config := config{}
    user = NewUser(config)
    ...
}

我建议您查看revel包中的config配置文件(https://github.com/revel/config),它被用于revel框架https://github.com/revel/revel中。

Revel 是否在解决一些不同、更复杂的问题?仅仅因为有“大锤”,我们并不需要使用它 :-) - gbulmer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接