go mysql init,Go教程:25 Go初始化init函数

Go教程:25 Go初始化init函数

9bc2daec89c881669e58a6e470c065d0.png

1. 什么是Go语言init函数

在Go中,预定义init()函数会触发执行init函数中的代码,使其在包的任何其他代码之前运行.

该代码将在import package后立即执行,并且可以在需要您的app以特定方式初始化,

例如,当您具有启动app的config或resource时.

import package 使用init函数的副作用来设置和初始化一些包的状态.

这通常用于register一个包和另一个包,以确保程序正在考虑代码的正确性.

尽管这init()是一个有用的工具,但有时会使代码难以阅读,因为难以搞清楚的所有包中的init()函数的执行.

因此,对于刚接触Go的开发人员来说,了解此功能的各个方面非常重要,

以便他们在coding时可以确保init()以清晰易懂的方式执行.

1.1 init函数的主要作用

初始化不能采用初始化表达式初始化的变量.

eg: 在init函数初始化rand函数的时间种子,初始化一个随机32长度app_secret字符串

程序运行前的注册.在gorm 中有这样一段带代码import _ "github.com/jinzhu/gorm/dialects/sqlite",相当于注册driver

实现sync.Once功能.如果您要创出单例,在init中初始化是一个很好的方式.

import _ "github.com/jinzhu/gorm/dialects/sqlite" 这种方式使用go get/mod 下载其他package

1.2 init函数的主要特点

init函数先于main函数自动执行,不能被其他函数调用;

init函数没有输入参数,返回值;

每个包可以有多个init函数;

包的每个源文件也可以有多个init函数,这点比较特殊;

同一个包的init执行顺序,golang没有明确定义,编程时要注意程序不要依赖这个执行顺序.

不同包的init函数按照包导入的依赖关系决定执行顺序.

2. init函数在go语言中执行的顺序

8acc808338a77de4179d94719e2a03e5.png

为了使用导入的包,首先必须将其初始化.

初始化总是以单线程执行,并且按照包的依赖关系顺序执行.这通过Golang的运行时系统控制.

正如上图所示:

初始化导入的包(递归导入)

对包块中声明的变量进行计算和分配初始值

执行包中的init函数

main.go

packagemainimport"fmt"var_int64=s()funcinit(){fmt.Println("开始执行init函数")}funcs()int64{fmt.Println("开始初始化const/var")return1}funcmain(){fmt.Println("开始执行main函数")}

执行go run main.go 代码输出结果

$ go run play.go

开始初始化const/var

开始执行init函数

开始执行main函数

即使包被导入多次,初始化只需要一次.如果是多层级的import package 安装上面图示顺序执行.

3. init函数的Side Effects副作用

在Go中,有时希望导入软件包不是出于其内容,而是出于导入软件包时发生的副作用(Side Effects).

这通常意味着init()在导入的代码中有一条语句在其他任何代码之前执行,

从而使开发人员可以操纵其程序启动时的状态.这种技术被称为导入副作用(Side Effects).

导入副作用的一个常见用例是在代码中注册功能,

这使程序包知道程序需要使用代码的哪一部分.

在image封装中,例如,该image.Decode功能需要知道它正试图解码(其图像的格式jpg,png,gif等),

然后才能执行.您可以通过首先导入具有init()语句副作用(Side Effects)的特定程序来完成此操作.

假设您正尝试对一个.png文件执行image.Decode.代码段如下:

...funcdecode(readerio.Reader)image.Rectangle{m,_,err:=image.Decode(reader)iferr!=nil{log.Fatal(err)}returnm.Bounds()}...

上面这对代码会被编译出来,不会报错.但是当我们decode png文件的时候程序将会报错.

要修复,我们需要先为image.Decode注册图片格式png.非常幸运的是image/png包init函数含一下声明.

image/png/reader.go

funcinit(){image.RegisterFormat("png",pngHeader,Decode,DecodeConfig)}

因此,如果我们import “image/png” 到我们上面的解码代码中,然后在image/png中的 image.RegisterFormat()函数将最先执行.

最终代码如下:

...import_"image/png"...funcdecode(readerio.Reader)image.Rectangle{m,_,err:=image.Decode(reader)iferr!=nil{log.Fatal(err)}returnm.Bounds()}

这将设置状态并注册我们需要的png版本image.Decode().

该注册将作为导入image/png包的副作用而执行.

您可能之前已经注意到空白标识符_(下划线)”image/png”.

这是必需的,因为Go不允许您导入程序中未使用的程序包.

通过包括空白标识符,导入本身的值将被丢弃,从而仅导入的副作用得以解决.

这意味着,即使我们从不image/png在代码中调用该包,也可以出于副作用而将其导入.

了解何时需要导入软件包的副作用(import _ “your/package”)非常重要.

如果没有正确注册,则程序可能会编译成功,但在运行时无法正常运行.

标准库中的软件包将在其文档中声明需要这种类型的导入.

如果编写的程序包需要导入以产生副作用,

则还应确保记录了init()正在使用的语句,以便导入程序包的用户将能够正确使用它.

The End

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助.

谢谢大家对mojotv.cn的支持.喜欢这个网站麻烦帮忙添加到收藏夹,关闭广告屏蔽浏览器插件

如果有疑问大家可以留言交流,添加我的微信好友:felixarebest 微博账号: MojoTech向我提问.

线上交流工具: 在你的terminal中输入 ssh $用户@mojotv.cn

在你的terminal中输入 ssh mojotv.cn hn 查看最新 hacknews

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值