假设一个golang项目的三个源文件a.go,b.go, c.go,都定义了function inint(){}函数,
其中c.go文件初始化了一个全局变量globalVar,同时a.go 或者b.go的init func 引用了这个全局变量globalVar。
那么这个时候就会出现一个问题,在a.go和 b.go的init func中 globalVar的引用是空值。
文件结构#
1
2
3
4
5
6
7
8
9
| ❯ tree
.
├── a.go
├── b.go
├── c.go
├── go.mod
└── main.go
0 directories, 5 files
|
源代码#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
// file `a.go`
package main
import "fmt"
func init() {
// globalVar is empty
fmt.Println("globalVar in a.go:", globalVar)
}
// file `b.go`
package main
import "fmt"
func init() {
// globalVar is empty
fmt.Println("globalVar in b.go:", globalVar)
}
// file `c.go`
package main
import (
"fmt"
"time"
)
func init() {
globalVar = initVar()
fmt.Println("globalVar in c.go:", globalVar)
}
func initVar() string {
time.Sleep(20 * time.Millisecond)
return "late is better than never"
}
// file `main.go`
package main
import "fmt"
var globalVar = ""
func main() {
fmt.Println("vim-go")
}
|
result#
1
2
3
4
5
6
| ❯ go build -o demo
❯ ./demo
globalVar in a.go:
globalVar in b.go:
globalVar in c.go: late is better than never
vim-go
|
解决办法#
简单的解决办法可以是重命名c.go为0a.go保证0a.go中的init最早执行完成,
这个解决方案的优点是可以不用修改代码,但是不够优雅。
比较好的解决方式应该是,不要在init func里初始化全局变量,应该直接在top block context中对全局变量初始化:
1
2
3
4
5
6
7
8
| // file `c.go`
package main
var globalVar = initVar()
func init() {
// ...
}
|