起因
吃完饭,跟同事们散步,聊到了项目中公共SDK库中的一些缺陷。由来是项目才启动时,封装公共库的员工,在库中使用init函数进行配置文件的解析。从而使业务团队在编写单元测试时,带来了问题。 突然,我想到一个问题,如果乱用了init函数,而该函数中没有日志输出,导致进程假死,那么有什么手段可以快速定位到?
init函数
举例说明
在github.com/go-sql-driver/mysql/driver.go中:
func init() {
if driverName != "" {
sql.Register(driverName, &MySQLDriver{})
}
}
会对sql.Register进行初始化操作。
怎么使用
// package-init/init-mysql/main.go
package main
import (
"database/sql"
"log"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
panic(err)
}
log.Println(db)
//...
}
-
在导入声明中,我们必须导入语句 -
第一个“database/sql”导入标准库包。 -
_“github.com/go-sql-driver/mysql”是一个空白导入,–>调用了init函数 -
然后在主函数中,我们调用 “database/sql”中的Open函数。它将打开与数据库的连接。
是什么
init函数的目的是:package 初始化。 有以下的特点:
-
没有参数 -
没有返回值—>无法进行错误的返回。
以上例子:我们的主包中没有 init 函数的踪迹…因此这是完全可以理解的,因为:
-
mysql的驱动程序中的 init 函数未导出。 -
因此不可能从另一个包中调用它。
如果我们不调用init函数,Go如何注册驱动程序呢?
-
我们的程序将调用包中的 init 函数。 -
之所以调用它,是因为我们使用空白导入 _
语句导入了驱动程序。
当您使用空白导入语句导入包时,将运行包初始化函数。 请注意,驱动程序包的作者还可以删除 init 函数,特别是指示用户手动调用 Register 函数。
初始化的规则
package的初始化,按照 go 规范定义的特定顺序进行:
-
初始化导入的包: -
包中变量初始化 -
运行初始化函数 -
然后当前package本身初始化 -
变量已初始化 -
运行初始化函数Init 函数
按顺序运行。换句话说,init 函数不是同时运行的。
★
另外:一个包中可以包含多个init函数,执行的顺序是按照文件的排序执行。
”
回到问题
如果乱用了init函数,而该函数中没有日志输出,导致进程假死,那么有什么手段可以快速定位到?举例, 目录如下:
├── baz
│ └── baz.go
├── dtm-demo
├── foo
│ ├── a.go
│ ├── bar
│ │ └── bar.go
│ ├── foo2.go
│ └── foo.go
└── main.go
每个包中都包含一个init函数,而foo包中每个文件都存在一个init函数, 输出如下:
in baz
in bar
in a
in foo
in foo2
hello foo
Hello Bar
如何定位init函数,有以下几个方式:暴力思路:从main函数入手,对每个main导入的包进行递归查询,查看每个包以及包依赖包有没有init函数。这种方式可以说非常耗时以及慢了。工具的使用:
-
**go tool nm**
:可以查看golang程序的符号表。 那么我们可以通过以下命令输出当前二进制文件包含的init函数:
go tool nm ./dtm-demo |grep ".init.[0-9]"
命令的目的是输出包含 init.<序号>的函数。进而通过排序标准包的影响来定位问题。(一般情况下使用init函数很少,所以可以从自家的代码入手排查)
-
使用 go-callvis
进行程序调用链的查看。
结论
非必要的情况下,尽量避免使用init函数。init函数不会失败(只有当处理程序为nil时才会发生),init函数可能会导致一些问题:
-
限制错误管理,无返回值,无显式的调用。 -
使测试实现变得复杂(例如,必须设置外部依赖项,这在单元测试的范围内可能是不必要的)。
原文始发于微信公众号(小唐云原生):【golang】init函数的一些理解
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/247513.html