V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
darluc
V2EX  ›  Go 编程语言

「译」Golang 中的 init 函数

  •  2
     
  •   darluc · 2021-01-10 22:10:40 +08:00 · 1981 次点击
    这是一个创建于 1450 天前的主题,其中的信息可能已经有所发展或是发生改变。

    「阅读全文」

    标识符 main 无所不在。每个 Go 程序的执行都是从 main 包中一个拥有相同名字的函数开始的。当这个 main 函数返回时,整个程序也退出了执行。init 函数也扮演着特定的角色,本文会描述它们的特性并介绍它们的使用方法。

    init 函数是定义在包级别的,它被用于:

    • 初始化无法使用表达式初始化的变量
    • 检查和修复程序的状态
    • 注册
    • 执行一次性的运算
    • 以及其它

    除了下面要介绍一些区别,你可以将任何在一般函数中有效的代码放在其中。

    包的初始化

    要使用一个引入的包,首先它需要被初始化。这是由 Golang 的运行系统来完成的,由以下几步(顺序很重要)组成:

    1. 初始化引入的包(递归释义)
    2. 计算并初始化赋值包级别的变量
    3. 执行包内的 init 方法

    包的初始化过程只会被执行一次,即使它被多次引用

    顺序

    Go 语言的包可以包含许多文件。那么在这些包和文件中,变量的初始化和 init 函数的执行顺序是怎样的呢?首先,初始化依赖机制会起作用(详情可以查看“Go 中的初始化依赖”)。当依赖工作完成后,必须决定先初始化 a.go 文件中的变量还是 z.go 文件中的变量。这依赖于文件在编译器中出现的顺序。如果 z.go 先被提交给构建系统,那么它的变量就会先于 a.go 中的变量初始化。init 方法的调用也遵守相同的顺序。语言规格定义中建议总是采用相同的顺序,并且将包中的文件按单词拼写顺序传入:

    为了保证初始化行为可稳定复现,构建系统应该倾向于将同一个包中的多个文件按文件名的单词拼写顺序传递给编译器。

    不过对于移植性较差的程序来说也可以使用特别的顺序。我们用下面的例子看看这些是如何一起工作的:

    sandbox.go

    package main
    import "fmt"
    var _ int64 = s()
    func init() {
        fmt.Println("init in sandbox.go")
    }
    func s() int64 {
        fmt.Println("calling s() in sandbox.go")
        return 1
    }
    func main() {
        fmt.Println("main")
    }
    

    a.go

    package main
    import "fmt"
    var _ int64 = a()
    func init() {
        fmt.Println("init in a.go")
    }
    func a() int64 {
        fmt.Println("calling a() in a.go")
        return 2
    }
    

    z.go

    package main
    import "fmt"
    var _ int64 = z()
    func init() {
        fmt.Println("init in z.go")
    }
    func z() int64 {
        fmt.Println("calling z() in z.go")
        return 3
    }
    

    程序输出:

    calling a() in a.go
    calling s() in sandbox.go
    calling z() in z.go
    init in a.go
    init in sandbox.go
    init in z.go
    main
    

    属性

    init 函数不接受任何参数,也没有返回值。于 main 相比,标识符 init 是没有被申明的,所以无法被引用:

    「阅读全文」

    3 条回复    2021-01-12 17:44:51 +08:00
    CEBBCAT
        1
    CEBBCAT  
       2021-01-10 23:45:08 +08:00 via Android
    我觉得标题中的译可以或者说应该用方括号,就是那种内部涂黑的,V2 好像会转化那种括号到这个: [,也不错
    iugo
        2
    iugo  
       2021-01-11 17:45:47 +08:00
    undertonememorie
        3
    undertonememorie  
       2021-01-12 17:44:51 +08:00
    单个文件多个 init 执行顺序是什么?同一 package 下,init 的执行顺序又是什么,
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1425 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 17:10 · PVG 01:10 · LAX 09:10 · JFK 12:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.