我试图通过在main
方法中调用godotenv.Load
来加载环境变量,但问题是我在其他包中有init
函数,它们在从.env文件加载环境变量之前运行,因此造成了麻烦。
对此有什么变通办法吗?
以下是Golang包初始化的规范:https://go.dev/ref/spec#Package_initialization
简而言之,对于给定的包,
-
当前包导入的所有包都按照源文件名的词法顺序初始化,然后按照在每个源文件中导入的顺序初始化。
-
当前包中的所有包级别变量都按依赖关系顺序进行初始化。
-
然后,当前包中定义的所有
init()
函数都按源文件名的词法顺序执行,然后在每个文件中按文档顺序执行。 -
一旦初始化了所有包,就会调用
main()
函数,开始执行程序。
根据规范,
包初始化——变量初始化和init函数的调用——在单个goroutine中按顺序发生,每次一个包。
您所需要做的就是确保环境变量的加载/设置发生在首先初始化的包中但是请注意go fmt
将按字母顺序排列您的imports
。
因此,给定一个包含4个包的程序,main
、alpha
、bravo
和charlie
,
依赖关系为:
main
导入alpha
和bravo
,并且alpha
导入charlie
并且每个包具有多个CCD_ 17函数(源代码如下(,执行go run main.go
将以下内容写入控制台:
charlie/main.go: init: 1
charlie/main.go: init: 2
charlie/main.go: init: 3
alpha/main.go: init: 1
alpha/main.go: init: 2
alpha/main.go: init: 3
bravo/main.go: init: 1
bravo/main.go: init: 2
bravo/main-.go: init: 3
main.go: init: 1
main.go: init: 2
main.go: init: 3
main(): executing
./main.go
package main
import (
"fmt"
"some-host/init-example/alpha"
"some-host/init-example/bravo"
)
func init() {
fmt.Println("main.go: init: 1")
}
func init() {
fmt.Println("main.go: init: 2")
}
func main() {
fmt.Println("main(): executing")
alpha.DoSomething()
bravo.DoSomething()
}
func init() {
fmt.Println("main.go: init: 3")
}
./alpha/alpha.go
package alpha
import (
"fmt"
"some-host/init-example/charlie"
)
func init() {
fmt.Println("alpha/main.go: init: 1")
}
func init() {
fmt.Println("alpha/main.go: init: 2")
}
func DoSomething() {
charlie.DoSomething()
}
func init() {
fmt.Println("alpha/main.go: init: 3")
}
./bravo/bravo.go
package bravo
import "fmt"
func init() {
fmt.Println("bravo/main.go: init: 1")
}
func init() {
fmt.Println("bravo/main.go: init: 2")
}
func DoSomething() {
}
func init() {
fmt.Println("bravo/main-.go: init: 3")
}
./charlie/charlie.go
package charlie
import "fmt"
func init() {
fmt.Println("charlie/main.go: init: 1")
}
func init() {
fmt.Println("charlie/main.go: init: 2")
}
func DoSomething() {
}
func init() {
fmt.Println("charlie/main.go: init: 3")
}