背景


​ 我在测试某个文件的时候,文件的具体内容没有错误,但是会报错invalid memory(空指针引用),debug后发现是log.Logger == nil ,但是我的Logger是放在init函数中的,没道理没有初始化,由此我查了GPT想到了目录相关的路径依赖问题,但是很快NX就帮我否决了,我自己想想也是,怎么可能是路径问题,NX还问我了一个问题

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
// 附上代码
// tiktok/common/oss/oss_test.go 中
func TestNew(t *testing.T) {
log.Init()
AliyunInit()
CreateBucket("simple-tiktok-app")
log.Logger.Info("TestNew is success")
fmt.Println("TestNew is success")
}
// tiktok/common/oss/oss.go 中
func AliyunInit() {
client, err := oss.New("x","x","x")
if err != nil {
log.Logger.Error("aliyun oss init failed")
fmt.Println("aliyun oss init failed:", err)
return
}
log.Logger.Info("xxxxx")
AliyunClient = client
fmt.Println("aliyun oss init success")
}
// main.go
func init() {
once.Do(func() {
log.Init()
config.Init()
db.Init()
})
}

log.Logger.Info(“xxx”) 报错!

—– init函数 什么是 被执行

什么时候执行

第一反应 : 所有程序运行前执行?

查GPT的第二反应: 程序启动时,main函数之前运行?

正确答案: init 函数是在包被引用时执行的

为什么test.go不能执行

测试文件的特殊性:当你使用 go test 命令运行测试文件时,Go 测试工具会为测试文件创建一个新的虚拟包,这个虚拟包的名字通常是 "cmd/internal/test"。这个虚拟包包含了测试文件本身和其他被测试文件所依赖的所有包。因此,尽管你的测试文件引用了其他包,但这些包的 init 函数并不会在这个测试文件中被执行,而是在这个虚拟包中被执行

至此问题解决。。

衍生

由于 init函数是在包被引用时执行的

那么如果我只想要用init函数,而不使用包中的其他内容,咋办呐

1
_ "github.com/jinzhu/gorm/dialects/sqlite"

即可

init


解决完上面问题,不如学习一下init函数的知识

下面的知识纯属借鉴网上其他博客

五分钟理解golang的init函数 - 知乎 (zhihu.com)

  • init函数先于main函数自动执行,不能被其他函数调用;
  • 全局变量->init函数->main函数
  • 每个包可以有多个init函数且包的每个源文件也可以有多个init函数
  • 不同包的init函数按照包导入的依赖关系决定执行顺序。
  • 同一个包的init执行顺序,golang没有明确定义,编程时要注意程序不要依赖这个执行顺序。

初始化

golang变量的初始化 (qq.com)

怎么用好 Golang 的 init 函数 - 知乎 (zhihu.com)

总结

都是细节

NX简直不要太细