首页
技术博客
PHP教程
数据库技术
前端开发
HTML5
Nginx
php论坛
新用户注册
|
会员登录
PHP教程
技术博客
编程问答
PNG素材
编程语言
前端技术
Android
PHP教程
HTML5教程
数据库
Linux技术
Nginx技术
PHP安全
WebSerer
职场攻略
JavaScript
开放平台
业界资讯
大话程序猿
登录
极速注册
取消
热门标签 | HotTags
javascript
audio
function
httprequest
format
shell
loops
settings
cookie
cmd
java
export
heap
express
testing
dagger
command
web3
schema
instance
dll
process
regex
filter
get
frameworks
typescript
sum
controller
search
case
object
hashtable
spring
copy
rsa
client
iostream
vba
less
substring
js
emoji
php7
future
foreach
import
merge
python2
python
scala
random
hashset
perl
python3
hash
uri
bytecode
select
email
cpython
go
timezone
utf-8
subset
golang
md5
buffer
default
string
match
php8
blob
bash
const
keyword
byte
join
split
当前位置:
开发笔记
>
编程语言
> 正文
Go中的init函数
作者:暖暖252 | 来源:互联网 | 2024-09-27 15:01
main 标识符是随处可见的,每一个 Go 程序都是从一个叫 main 的包中的 main 函数开始的,当 main 函数返回时,程序执行结束。 init 函数也扮演着特殊的角色,接下来我们将描述下 init 函数的属性并介绍下怎么使用它们。
init 函数在包级别被定义,主要用于:
- 初始化那些不能被初始化表达式完成初始化的变量
- 检查或者修复程序的状态
- 注册
- 仅执行一次的计算
- 更多其它场合
除了下面将要讨论到的一些差异外,你还可以在正则函数中放置任何[有效](https://golang.org/ref/spec#FunctionBody)的内容。
## 包的初始化
要想使用导入的包首先需要初始化它,这是由golang的运行系统完成的,主要包括(顺序很重要):
1. 初始化导入的包(递归的定义)
2. 在包级别为声明的变量计算并分配初始值
3. 执行包内的 init 函数(下面的空白标识符就是一个例子)
> 不管包被导入多少次,都只会被初始化一次。
## 顺序
Go 的包中有很多的文件,如果变量和函数在包的多个文件当中,那么变量的初始化和 init 函数的调用顺序又是什么样的呢?首先,初始化依赖机制会启动(更多 [Go 中的初始化依赖](https://studygolang.com/articles/13158))当初始化依赖机制完成的时候,就需要决定 `a.go` 和 `z.go` 中的初始化变量谁会被更早的处理,而这要取决于呈现给编译器的文件顺序。如果 `z.go` 先被传递到构建系统,那么变量的初始化就会比在 `a.go` 中先一步完成,这也同样适用于 init 函数的触发。Go 语言规范建议我们始终使用相同的顺序传递,即按照词法顺序传递包中的文件名:
> 为了保证可重复的初始化行为,构建系统鼓励按照词法文件名的顺序将属于同一个包中的多个文件呈现给编译器。
但依赖特定顺序对于不关注可移植性的程序是一种方式(译注:但不建议依赖 init 初始化顺序)。让我们来看一个例子,看看它们是如何一起工作的:
### sandbox.go
```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
```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
```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 没有被声明所以也就不能被引用:
```go
package main
import "fmt"
func init() {
fmt.Println("init")
}
func main() {
init()
}
```
在编译时这里会给出一个 “undefined:init” 错误。( init 函数不能被引用)
> 正式的来讲 init 标示符不会引入绑定,就像空白标示符('_')表现的一样。
在同一个包或者文件当中可以定义很多的 init 函数:
### sandbox.go
```go
package main
import "fmt"
func init() {
fmt.Println("init 1")
}
func init() {
fmt.Println("init 2")
}
func main() {
fmt.Println("main")
}
```
### utils.go
```go
package main
import "fmt"
func init() {
fmt.Println("init 3")
}
```
### 输出:
```
init 1
init 2
init 3
main
```
init 函数在标准库中也被频繁的使用,例如:[*main*](https://github.com/golang/go/blob/2878cf14f3bb4c097771e50a481fec43962d7401/src/math/pow10.go#L33), [*bzip2*](https://github.com/golang/go/blob/2878cf14f3bb4c097771e50a481fec43962d7401/src/compress/bzip2/bzip2.go#L479)还有 [*image*](https://github.com/golang/go/blob/2d573eee8ae532a3720ef4efbff9c8f42b6e8217/src/image/gif/reader.go#L511)包。
...
init 函数最常见的用法就是为初始化表达式中不能被计算的那部分分配一个值:
```go
var precomputed = [20]float64{}
func init() {
var current float64 = 1
precomputed[0] = current
for i := 1; i
precomputed[i] = precomputed[i-1] * 1.2
}
}
```
使用 for 循环作为[*表达式*](https://golang.org/ref/spec#Expression)(Go 语言中的语句)是不可能的,所以将这些放到 init 函数中就能够很好的解决这些问题。
## 仅仅为了使用包的副作用(包的初始化)而导入包
Go 语言对没有使用的导入是非常严格的。有时候程序员导入一个包可能只想要使用 init 函数的功能,例如一些引导工作。空白标示符就是一个不错的方式:
```go
import _ "image/png"
```
它甚至在[*image*](https://github.com/golang/go/blob/0104a31b8fbcbe52728a08867b26415d282c35d2/src/image/image.go#L10)包中被提到。
如果上面的内容对你有所帮助请跟随我一起续写未来的故事吧,那也将成为我的动力。
---
## 参考资料
- [The Go Programming Language Specification - The Go Programming Language](https://golang.org/ref/spec#Package_initialization)
- [Blocks in Go](https://studygolang.com/articles/12632)
- [Initialization dependencies in Go](https://studygolang.com/articles/13158)
go
text
main
正则
https
c#
function
文件
编译
写下你的评论吧 !
吐个槽吧,看都看了
会员登录
|
用户注册
推荐阅读
get
golang常用库:配置文件解析库/管理工具viper使用
golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ...
[详细]
蜡笔小新 2024-12-28 13:47:52
search
编写有趣的VBScript恶作剧脚本
本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ...
[详细]
蜡笔小新 2024-12-28 09:46:23
get
Python 的 10 个开发技巧!太实用了
1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ...
[详细]
蜡笔小新 2024-12-27 18:36:54
search
[论文笔记] Crowdsourcing Translation: Professional Quality from Non-Professionals (ACL, 2011)
Time:4hoursTimespan:Apr15–May3,2012OmarZaidan,ChrisCallison-Burch:CrowdsourcingTra ...
[详细]
蜡笔小新 2024-12-28 13:39:05
get
Python配置文件读写指南
本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ...
[详细]
蜡笔小新 2024-12-28 08:39:55
get
技术分享:从动态网站提取站点密钥的解决方案
本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ...
[详细]
蜡笔小新 2024-12-28 04:11:47
get
Go语言基础:Hello World 实践
本文将介绍如何使用 Go 语言编写和运行一个简单的“Hello, World!”程序。内容涵盖开发环境配置、代码结构解析及执行步骤。 ...
[详细]
蜡笔小新 2024-12-27 21:29:35
get
Java并发编程:LinkedBlockingQueue的实际应用
本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ...
[详细]
蜡笔小新 2024-12-27 18:51:49
command
深入解析JVM垃圾收集器
本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践》第二版,详细探讨了JVM中不同类型的垃圾收集器及其工作原理。通过介绍各种垃圾收集器的特性和应用场景,帮助读者更好地理解和优化JVM内存管理。 ...
[详细]
蜡笔小新 2024-12-28 13:35:19
get
使用Objective-C和dispatch库实现并发素数计算
本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ...
[详细]
蜡笔小新 2024-12-28 08:44:35
get
深入理解Tornado模板系统
本文详细介绍了Tornado框架中模板系统的使用方法。Tornado自带的轻量级、高效且灵活的模板语言位于tornado.template模块,支持嵌入Python代码片段,帮助开发者快速构建动态网页。 ...
[详细]
蜡笔小新 2024-12-27 19:22:16
get
数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ...
[详细]
蜡笔小新 2024-12-27 18:29:55
get
java编写的简易计算器
主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ...
[详细]
蜡笔小新 2024-12-27 18:18:10
java
Dockerfile 编写与 Docker 网络配置详解
本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ...
[详细]
蜡笔小新 2024-12-27 17:31:41
java
深入理解Java中的volatile、内存屏障与CPU指令
本文详细探讨了Java中volatile关键字的作用机制,以及其与内存屏障和CPU指令之间的关系。通过具体示例和专业解析,帮助读者更好地理解多线程编程中的同步问题。 ...
[详细]
蜡笔小新 2024-12-27 17:26:33
暖暖252
这个家伙很懒,什么也没留下!
Tags | 热门标签
javascript
audio
function
httprequest
format
shell
loops
settings
cookie
cmd
java
export
heap
express
testing
dagger
command
web3
schema
instance
dll
process
regex
filter
get
frameworks
typescript
sum
controller
search
RankList | 热门文章
1
ppt中如何设置动作按钮?
2
《南出雀鼠谷答张说》翻译 原文赏析诗人唐李隆基
3
python实现KNN分类器——手写识别
4
一周工作总结--一次SQL优化记录
5
人脸识别系统实现
6
项目添加到cordova过程
7
java 如何自己写基类_一个实体类基类实现
8
java实现栈,队列数据结构
9
vue如何使用prerenderspaplugin预渲染进行数据的预取和预加载?
10
Android Studio 调试出现waiting for debugger的解决办法
11
NAVER China 诚聘 C++开发工程师
12
word文档纸张大小选项里没有A4纸的选项,怎么办?:word设置a4纸
13
cmake语法详解,cmake详细教程
14
我怎么才能每30分钟得到一个cron ? - How would I get a cron job to run every 30 minutes?
15
varnish2.04配置
PHP1.CN | 中国最专业的PHP中文社区 |
DevBox开发工具箱
|
json解析格式化
|
PHP资讯
|
PHP教程
|
数据库技术
|
服务器技术
|
前端开发技术
|
PHP框架
|
开发工具
|
在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved |
京公网安备 11010802041100号
|
京ICP备19059560号-4
| PHP1.CN 第一PHP社区 版权所有