特殊的init函数

栏目: Go · 发布时间: 5年前

内容简介:package组织go代码的一种形式,和python ,Java,c++等语言的包是具有同样的功能,在使用其他包的函数和结构体,变量时,必须先引入package的文件,package是定义方的语句,而import是使用方的语句。有时在package的文件中,能看到init函数,这种函数一般函数不一样,无法被调用(无论是包内还是包外)。init函数只在该文件被被引用时才执行(是import时,不是调用包函数时)。在go中,init和main函数都是特殊的存在,两者都不能定义参数和返回值,否则编译器直接报错。i

一、package 和init函数

package组织 go 代码的一种形式,和python ,Java,c++等语言的包是具有同样的功能,在使用其他包的函数和结构体,变量时,必须先引入package的文件,package是定义方的语句,而import是使用方的语句。有时在package的文件中,能看到init函数,这种函数一般函数不一样,无法被调用(无论是包内还是包外)。init函数只在该文件被被引用时才执行(是import时,不是调用包函数时)。

二、init函数的特殊性

在go中,init和main函数都是特殊的存在,两者都不能定义参数和返回值,否则编译器直接报错。init函数在同一个包内,同一个文件内都可以定义多个init函数,且在包依赖情况时,会优先执行依赖包的init函数。具体如下:

  1. init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等
  2. 每个包可以拥有多个init函数
  3. 包的每个源文件也可以拥有多个init函数
  4. 同一个包中多个init函数的执行顺序go语言没有明确的定义(说明)
  5. 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序
  6. init函数不能被其他函数调用,而是在main函数执行之前,自动被调用

三、init的执行顺序

init的执行顺序按照以下几个原则:

  1. 依赖包的init函数先执行,比如A 依赖于B,那么B的init函数先执行
  2. 不同包被引入的,按照引入的顺序执行
  3. 同一文件内的多个init函数,按照函数定义的顺序执行
  4. 引用包的init函数优先于 本文件内的init函数执行

demo:

package main

import (
    "Test/lib"
    "fmt"
)
func init() {
    fmt.Println("hello world")
}

func main() {
    fmt.Println("wint")
    lib.Mutable()
    lib.UnMutable()
}

lib库函数

package lib
import "fmt"
func init() {
    fmt.Println("empty init load 123")
}

func init() {
    fmt.Println("empty init load")
}

func Mutable() {

    var i = 1
    var b = true
    var f = 1.3
    var s = "hello world"
    fmt.Printf("%p, %p, %p, %p\n", &i, &b, &f, &s)

    i = 2
    b = false
    f = 1.4
    s = "hello me"
    fmt.Printf("%p, %p, %p, %p\n", &i, &b, &f, &s)
}

func UnMutable() {
    type S struct {
        Name string
        Index int
    }
    var m = map[string]string{
        "name": "map",
        "type":"map string",
    }
    var s = S {
        Name: "struct",
        Index : 1,
    }
    fmt.Printf("%p, %p\n", &m, &s)

    m["name"] = "map change"
    s.Name = "struct change"
    fmt.Printf("%p, %p\n", &m, &s)
}
//输出内容
empty init load 123
empty init load
hello world
wint
0xc00008c020, 0xc00008c028, 0xc00008c030, 0xc0000800a0
0xc00008c020, 0xc00008c028, 0xc00008c030, 0xc0000800a0
0xc00007c020, 0xc000088040
0xc00007c020, 0xc000088040

四、init的几个建议

init虽说是golang的一个特性,但也有一些不足,根据之前的经验总结如下:

  1. 尽量不要让init执行过多的程序,因为init是隐式执行的,如果过多代码执行,会造成程序不可控,一些隐藏问题无法快速发现
  2. 不要在文件内,定义多个init函数,防止init混乱问题,同时减少定义顺序带来的不可控问题
  3. 尽可能使用显示Init函数代替init函数,让调用方清楚知道被调用方做的申请。比如InitConn,可看出是初始化某个连接,这样在使用结束时,可显示释放连接。
  4. init中的全局变量注意要释放,否则在默认初始化后,没有即使得到释放,可能会造成资源占满情况出现。比如 mysql 连接。

以上所述就是小编给大家介绍的《特殊的init函数》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Game Programming Patterns

Game Programming Patterns

Robert Nystrom / Genever Benning / 2014-11-2 / USD 39.95

The biggest challenge facing many game programmers is completing their game. Most game projects fizzle out, overwhelmed by the complexity of their own code. Game Programming Patterns tackles that exac......一起来看看 《Game Programming Patterns》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具