我在我的项目中有以下布局:
MyProject
├── config
│ └── config.go
│ └── config_test.go
│ └── testdata
│ └── config.yaml
├── main.go
├── go.mod
├── go.sum
配置。Go文件负责加载应用的配置,它应该在第一次导入配置包时自动发生。因此,我在那里配置了一个init方法,它将加载所有相关设置并进行设置:
package config
import ( "os" )
var (
Propery_x string
Property_y string
Property_z string
)
func init() {
LoadSettings()
}
func LoadSettings(){
Property_x = os.Getenv("X")
Property_y = os.Getenv("Y")
Property_z = os.Getenv("Z")
.....
我在配置的init方法之前的单元测试中设置这些环境值有问题。Go文件被调用。我遵循了我在这里找到的一些指导方针,建议做以下事情:
package config
import (
"os"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
)
func TestMain(m *testing.M) {
os.Setenv("X", "500")
m.Run()
os.Exit(0)
}
func TestLoadSettings(t *testing.T) {
assert.Equal(t, "500", Property_x, "values arent equal..")
}
您可以理解,代码仍然使用默认值,并且在config.go的init()
之前没有设置env变量。
我考虑的另一个选项是:延迟加载。这样,我就不需要init方法,并且设置将在第一次有人试图访问配置时加载。
不要使用init
函数
在启动main
函数时调用config.LoadSettings
。在测试中,您还可以定义事情的确切顺序。
还有一些包可以使用与flags
包完全相同的语法加载配置文件、环境变量或命令行参数。例如namsral/标记
就像@TehSphinX建议的那样,我决定使用一个专门的方法来返回配置,而不是自动加载它。换句话说,我实现了延迟加载:
package settings
var (
settings *Settings
configLoaded *AtomicBoolean = &AtomicBoolean{sync.Mutex{}, false}
)
type AtomicBoolean struct {
mu sync.Mutex
val bool
}
type Settings struct {
property_x string
property_y string
property_z string
}
func (ab *AtomicBoolean) getValue() bool {
var val bool = false
ab.mu.Lock()
val = ab.val
ab.mu.Unlock()
return val
}
func (ab *AtomicBoolean) setValue(val bool) {
ab.mu.Lock()
ab.val = val
ab.mu.Unlock()
}
func GetSettings() *Settings {
if !settingsgLoaded.getValue(){
loadSettings()
}
}
func loadSettings(){
Property_x = os.Getenv("X")
Property_y = os.Getenv("Y")
Property_z = os.Getenv("Z")
...
settingsLoaded.setValue(true)
.....
现在在我的测试中,我可以设置环境变量,只有在调用GetSettings函数之后:
package settings
func TestLoadSettings(t testing.T){
os.Setenv("X',"500")
assert.Equal(GetSettings().property_x,"500")
}