在Go库中管理环境变量

huangapple go评论65阅读模式
英文:

managing env variables in Go libraries

问题

我正在使用Go语言编写一个库。有几个可配置的值,我想了解一些设置这些值的好方法。我考虑了以下几个选项:

  1. 使用os.Getenv()函数获取环境变量的值,无论在哪里使用它们。缺点是多次读取同一个环境变量。
  2. 创建一个配置文件,读取所有的配置变量,并将配置结构体传递给需要使用的地方。我不打算在多个地方传递这样的结构体。有些文件在启动时需要一个静态值。
  3. 使用init()函数;据我所知,这不被推荐,至少不推荐多次使用init()函数。

还有没有更简单、更清晰的方法推荐?

英文:

I am writing a library in Go. There are several configurable values and I am looking to understand some good ways to set these values. I have considered following options:

  1. use os.Getenv() to get values of env variables wherever they are to be used. Drawback is reading same env variable multiple times.
  2. Create a config file, read all config variables, and pass the config struct around. I do not intend to pass such struct around in multiple places. There are files which need a static value determined at startup.
  3. Use init() function; afaik this is not recommended, at least multiple init are not recommended.

Any more recommendations on a simpler and cleaner approach?

答案1

得分: 1

从配置文件或环境中读取设置应该在启动时完成。如果我理解正确,你的问题是关于如何将这些值注入到其他包中。

以下是一些想法。

  1. 一个包含所有设置的全局配置包。在启动时读取设置,然后在全局范围内使用。优点:所有设置都可以在任何地方使用。缺点:设置是可变的,考虑通过添加函数并不导出设置对象来使其只读。
  2. 在启动时读取设置后,将其注入到每个包中。需要设置的包可以有一个公共的Init(...)函数,接受所有必要的设置。不要使用init()。优点:没有大型的配置结构,只有必要的设置。缺点:到处都是全局变量,很容易变得混乱,可能会忘记调用Init()等。
  3. 要求设置:为了避免上述涉及全局变量的混乱,只需在使用设置的所有代码中要求设置:对于函数,将设置作为参数接受。如果有带有方法的结构体,更好:将设置作为需要定义的结构体字段。如果有构造函数,让构造函数接受设置。优点:没有全局变量,对设置的依赖清晰明确。缺点:可能不明显哪些值是应用程序设置,直到追溯其来源。

第3种方法是我最喜欢的方法,因为它可以更清楚地了解设置的来源和使用方式。

英文:

Reading settings from config files or the environment should be done at startup. If I understand correctly, your question is about how these values should be injected into other packages.

Here is a few ideas.

  1. A global config package that contains all settings. The settings are read on startup and are then globally available here. Pro: all settings available, everywhere. Con: Settings are mutable, consider making them read only by adding functions and not exporting the settings object.
  2. After reading in the settings on startup, inject them into each package. A package that requires a setting can have a public Init(...) function that accepts all necessary settings. Don't use init(). Pro: no big config structs, only necessary settings. Con: globals all over the place, can become messy very fast, you can forget to call Init(), etc.
  3. Require settings: To avoid the chaos involving globals described above, just require settings in all code that uses them: For a function, accept the setting as an argument. If you have a struct with methods, even better: Make the setting a field of the struct that needs to be defined. If you have a constructor, have that constructor accept the setting. Pro: No globals, dependencies on settings are clear. Con: It might not be obvious which values are application settings right away, until you trace back their origin.

Number 3 is my favorite method since imho it makes it much more clear where
settings are coming from and how they are being used.

huangapple
  • 本文由 发表于 2022年11月14日 17:40:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/74429580.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定