首页
技术博客
PHP教程
数据库技术
前端开发
HTML5
Nginx
php论坛
新用户注册
|
会员登录
PHP教程
技术博客
编程问答
PNG素材
编程语言
前端技术
Android
PHP教程
HTML5教程
数据库
Linux技术
Nginx技术
PHP安全
WebSerer
职场攻略
JavaScript
开放平台
业界资讯
大话程序猿
登录
极速注册
取消
热门标签 | HotTags
client
instance
cookie
random
c语言
rsa
byte
string
const
solr
integer
main
filter
search
golang
join
function
javascript
httprequest
case
fetch
schema
input
hashcode
jsp
ip
scala
loops
md5
utf-8
frameworks
select
process
vbscript
replace
perl
uml
plugins
heap
get
timezone
timestamp
less
vba
triggers
python
metadata
int
uri
bytecode
go
php8
cmd
python3
settings
match
import
foreach
iostream
range
sum
email
install
web
hook
regex
express
yaml
flutter
hashtable
audio
window
char
cPlusPlus
typescript
default
cSharp
ascii
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
文件
编译
写下你的评论吧 !
吐个槽吧,看都看了
会员登录
|
用户注册
推荐阅读
ip
Python3爬虫入门:pyspider的基本使用[python爬虫入门]
Python学习网有大量免费的Python入门教程,欢迎大家来学习。本文主要通过爬取去哪儿网的旅游攻略来给大家介绍pyspid ...
[详细]
蜡笔小新 2024-11-22 18:00:41
byte
Requests库的基本使用方法
本文介绍了Python中Requests库的基础用法,包括如何安装、GET和POST请求的实现、如何处理Cookies和Headers,以及如何解析JSON响应。相比urllib库,Requests库提供了更为简洁高效的接口来处理HTTP请求。 ...
[详细]
蜡笔小新 2024-11-21 13:17:41
utf-8
基于SSM框架的在线考试系统:随机组卷功能详解
本文深入探讨了基于SSM(Spring, Spring MVC, MyBatis)框架构建的在线考试系统中,随机组卷功能的设计与实现方法。 ...
[详细]
蜡笔小新 2024-11-22 19:00:26
schema
binlog2sql,你该知道的数据恢复工具
binlog2sql,你该知道的数据恢复工具 ...
[详细]
蜡笔小新 2024-11-22 18:58:43
schema
Ubuntu 14.04 环境下搭建 Caffe(仅限 CPU)
本文详细介绍了如何在 Ubuntu 14.04 系统上搭建仅使用 CPU 的 Caffe 深度学习框架,包括环境准备、依赖安装及编译过程。 ...
[详细]
蜡笔小新 2024-11-22 16:43:30
case
利用Node.js实现PSD文件的高效切图
本文介绍了如何通过Node.js及其psd2json模块,快速实现PSD文件的自动化切图过程,以适应项目中频繁的界面更新需求。此方法不仅提高了工作效率,还简化了从设计稿到实际应用的转换流程。 ...
[详细]
蜡笔小新 2024-11-22 13:21:24
cookie
Nginx 配置下 Chrome 和 Firefox 对静态资源缓存处理差异
在使用 Nginx 作为服务器时,发现 Chrome 能正确从缓存中读取 CSS 和 JS 文件,而 Firefox 却无法有效利用缓存,导致加载速度显著变慢。 ...
[详细]
蜡笔小新 2024-11-21 19:57:43
utf-8
Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ...
[详细]
蜡笔小新 2024-11-21 18:39:23
md5
Oracle VM VirtualBox 使用指南:创建静态网页及高级功能
本文详细介绍了如何在Oracle VM VirtualBox中实现主机与虚拟机之间的数据交换,包括安装Guest Additions增强功能,以及如何利用这些功能进行文件传输、屏幕调整等操作。 ...
[详细]
蜡笔小新 2024-11-21 18:13:22
md5
CSS Border 属性:solid 边框的使用详解
本文详细介绍了如何在CSS中使用solid边框属性,包括其基本语法、应用场景及高级技巧,适合初学者和进阶用户参考。 ...
[详细]
蜡笔小新 2024-11-21 18:11:20
main
Singleton单例模式和DoubleChecked Locking双重检查锁定模式
问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ...
[详细]
蜡笔小新 2024-11-21 15:14:45
utf-8
web: _show -> _info 造轮子编程
问题场景用Java进行web开发过程当中,当遇到很多很多个字段的实体时,最苦恼的莫过于编辑字段的查看和修改界面,发现2个页面存在很多重复信息,能不能写一遍?有没有轮子用都不如自己造。解决方式笔者根据自 ...
[详细]
蜡笔小新 2024-11-21 10:21:24
utf-8
解决SQL Server中几何类型列的INTERSECT操作问题
本文探讨了在SQL Server中处理几何类型列时遇到的INTERSECT操作限制,并提供了解决方案,包括通过转换数据类型和使用额外表结构的方法。 ...
[详细]
蜡笔小新 2024-11-20 20:09:58
ip
C# 中创建和执行存储过程的方法
本文详细介绍了如何使用 C# 创建和调用 SQL Server 存储过程,包括连接数据库、定义命令类型、设置参数等步骤。 ...
[详细]
蜡笔小新 2024-11-19 19:55:59
ip
Fiddler 安装与配置指南
本文详细介绍了Fiddler的安装步骤及配置方法,旨在帮助用户顺利抓取用户Token。文章还涵盖了一些常见问题的解决方案,以确保安装过程顺利。 ...
[详细]
蜡笔小新 2024-11-22 11:36:57
暖暖252
这个家伙很懒,什么也没留下!
Tags | 热门标签
client
instance
cookie
random
c语言
rsa
byte
string
const
solr
integer
main
filter
search
golang
join
function
javascript
httprequest
case
fetch
schema
input
hashcode
jsp
ip
scala
loops
md5
utf-8
RankList | 热门文章
1
U盘自动化安装CentOS7.4
2
mysql 分段解析_MYSQL分段统计
3
开发笔记:异常的分类与使用
4
centos apache php 环境,CentOS 7 搭建 Apache + PHP + MySQL 环境
5
java面试servlet+jsp
6
eclipse导入原代码打包war包的方法
7
python中算法是什么意思_什么是算法?Python中的基础算法有几种?
8
IIS服务器配置NXLog进行syslog转发(并解决GMT+8小时时差问题)
9
axios 前端请求接口 跨域问题 Vue实现跨域请求
10
WirePlumber更新到0.4.13版本,增加了新的功能、改进和错误修复
11
怎么还不见2005的中文版出来的?
12
linux rhel6 nvidia 卡 在启动界面,RHEL6上安装Nvidia显卡驱动
13
mysql 如何提高查询速度.
14
使用新版 winsw 注册 windows 系统服务无法启动及停止问题
15
计算机网络应用基础练习题,2017计算机应用基础复习题「附答案」
PHP1.CN | 中国最专业的PHP中文社区 |
DevBox开发工具箱
|
json解析格式化
|
PHP资讯
|
PHP教程
|
数据库技术
|
服务器技术
|
前端开发技术
|
PHP框架
|
开发工具
|
在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved |
京公网安备 11010802041100号
|
京ICP备19059560号-4
| PHP1.CN 第一PHP社区 版权所有