特殊的init函数

yushu1987 · · 96 次点击 · · 开始浏览    

一、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连接。

本文来自:简书

感谢作者:yushu1987

查看原文:特殊的init函数

96 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传