假设一个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() {
// ...
}
|