package
💥本文章所有相关go代码参考自go 1.18+版本
package
包的概念
- 使用包来组织管理代码,包是结构化代码的一种方式。
- 每个
.go
文件都必须归属于某一个包,每个.go
文件都可能有init()
函数。 - 包名在源文件中第一行通过关键字
package
指定,包名要小写。
|
|
- 每个目录下面可以有多个
.go
文件,这些文件只能属于同一个包,否则编译时会报错。 - 同一个包下的不同
.go
文件相互之间可以直接引用变量和函数,所以这些文件中定义的全局变量和函数不能重名。 Go
语言的可执行应用程序必须有main
包,而且在main
包中必须且只能有一个main()
函数。main
函数是应用程序运行开始的入口,在main
包中可以使用init()
函数。
Go
语言不强制要求包的名称和文件所在目录名称相同,但是这两者最好保持相同,否则很容易引起歧义。- 因为导入包的时候会使用目录名作为包的路径,而代码中使用时,却要使用包的名称。
包的初始化
- 可执行应用程序的初始化和执行都起始于
main
包。 - 如果
main
包的源代码中没有包含main()
函数,则会引发构建程序错误undefined: main.mian
。 main()
函数即没有参数,也没有返回类型,init()
函数和main()
函数在这一点上一样。- 如果
main
包还导入了其他的包,那么在编译时会将它们依次导入。- 有时一个包会被多个包同时导入,那么它只会被导入一次(如很多包可能都会用到
fmt
包,但它只会被导入一次,因为没有必要导入多次)
- 有时一个包会被多个包同时导入,那么它只会被导入一次(如很多包可能都会用到
- 当所有被导入的包都加载完毕
- 就会对
main
包中的包级常量和变量进行初始化 - 然后执行
main
包中的init()
函数,最后执行main()
函数 - 导入包的顺序:导入包文件,对(全局)常量和变量进行初始化,然后执行
init()
函数(如果函数存在的情况下)
- 就会对
Go
语言中的init()
函数常用于包的初始化,该函数是Go
语言的一个重要特征。init
函数是用于程序执行前进行包的初始化的函数,例如初始化包里的变量等。- 每个包可以拥有多个
init
函数,(同一个包下不同的.go
文件中都允许定义init()
函数)。 - 同一个包中的多个
init()
函数的执行顺序是随机的。 - 不同包的
init()
函数按照包导入的依赖关系决定该函数的执行顺序。 init()
函数不能被其他函数调用,其在main函数执行之前,自动被调用。
包的导入
Go
语言程序通过导入import
关键字将一组包链接在一起通过导入包为程序所使用,程序中未使用的包,不能导入进来。- 导入操作会使用目录名作为包的路径而不是包名,实际应用中一般会保持两者一致。
- 例如标准包中定义的
big
包:package big
;导入时语句为import "math/big"
。- 导入时源代码在
$GOROOT
目录下的src/math/big
目录中。 - 程序代码使用
big.Int
时,big
指的是.go
文件中定义的包名称。
- 导入时源代码在
- 当导入多个包时,一般按照字母顺序排列包名称。
- 为避免名称冲突,同一包中所有对象的标识符必须唯一,但是相同的标识符可以在不同的包中使用,因为可以使用包名来区分它们。
|
|
- 导入多个包的常见的方式。
|
|
|
|
- 三种特殊的包导入
import (. "fmt")
- 点操作含义是包导入之后,在调用这个包的函数时,可以省略前缀的包名。
- 如
fmt.Println("hello world")
可以写成Println("hello world")
。
import (f "fmt")
- 别名操作就是可以把包命名成另外一个容易记住的名字。
- 如
fmt.Println("hello world")
可以写成f.Println("hello world")
。
import (_ "fmt")
_
操作是引入某个包,但不直接使用包里的函数,而是调用该包里面的init
函数。- 有时在开发中由于某种原因某个原来导入的包现在不在使用,也可以采用这种方式处理。
|
|
标准库
- 在Go语言的安装目录里包含标准库的各种包,在
$GOROOT/src
中可以看到源码,可以根据情况自行重新编译。 - 访问https://golang.google.cn/pkg/#stdlib了解更多详情。
|
|
从github
安装包
- 如果想安装
github
上的项目到本地计算机,可打开终端执行:go get -u github.com/ffhelicopter/tmm
。 - 现在这台计算机上的其他
Go
引用程序也可以通过导入路径github.com/ffhelicopter/tmm
来使用。import "github.com/ffhelicopter/tmm"
Go
对包的版本管理不是很友好,至少在go1.10
前是如此,不过现在第三方项目做得不错.- 有兴趣的读者可以了解一下(
glide
、godep
、govendor
). Gomodules
是1.11版本解决“包依赖管理”的实验性技术方案,后面章节学习。
- 有兴趣的读者可以了解一下(
导入外部安装包
- 如果要在应用中使用一个或多个外部包,可以使用
go install
在本地计算机上安装它们。 go install
是自动包安装工具,如需要将包安装到本地,它会从远端仓库下载包,完成检出、编译和安装。- 包安装的先决条件是要自动处理包自身依赖关系,被依赖的包也会安装到子目录下。
- 如果想使用
https://github.com/gocolly/colly
这种托管在Google Code
、GitHub
和Launchpad
等代码网站上的包。- 也可以通过如下命令安装:
go install github.com/gocolly/colly
。
- 也可以通过如下命令安装:
- 将一个名为
github.com/gocolly/colly
的包安装在$GoPATH/pkg/
目录下。 go install/build
用来编译包和依赖的包,区别如下:go build
只对main
包有效,在当前目录编译生成一个可执行的二进制文件,依赖包生成的静态库文件放在$GOOATH/pkg
。go install
一般生成静态文件,放在$GOPATH/pkg
目录下,文件扩展名为a。- 如果为
main
包,运行go build
则会在$GOPATH/bin
生成一个可执行的二进制文件。
使用Godoc
- 在程序中一般都会使用注释,按照一定规则,
Godoc
工具会收集这些注释并产生一个技术文档。 Godoc
会为每个文件生成一系列的网页。- 访问
Godoc
文档的方法是:- 命令行下进入目录并输入命令:
godoc -http=:6060 -goroot="."
。 - 然后在浏览器中打开地址:
http://localhost:6060
。 - 此时会看到本地的
Godoc
页面,从左到右一次显示出目录中的包。 - 或者直接在浏览器中打开地址
http://localhost:6060/pkg/go42/chapter-4/4.2/1/
。
- 命令行下进入目录并输入命令:
Go
程序的编译
- 在
Go
语言中,和编译有关的命令主要是go run
、go build
、go install
这三个命令。 go run
只能作用于main
包文件。- 先运行
compile
命令生成.a
文件。 - 然后链接命令生成最终可执行文件并运行程序,此过程中产生的是临时文件。
- 在
go run
退出前会删除这些临时文件(含.a
文件和可执行文件)。 - 最后直接在命令行输出程序执行结果。
go run
命令在第二次执行的时候,如果发现导入的代码包没有发生变化。- 则不会再次编译这个导入的代码包,而是直接进行链接生成最终可执行文件并运行程序。
- 先运行
go install
用于编译并安装指定的代码包及它们的依赖包。- 并且将编译后生成的可执行文件放到
bin
目录下($GOPATH/bin
)。 - 编译后的包文件放到当前工作区的
pkg
的平台相关目录下。
- 并且将编译后生成的可执行文件放到
go build
用于编译指定的代码包以及它们的依赖包。- 如果用来编译非
main
包的源码,则只做检查性的编译,而不会输出任何结果文件。 - 如果是一个可执行程序的源码(即
main
包),过程与go run
大体相同,只是会在当前目录生成一个可执行文件。
- 如果用来编译非
- 使用
go build
是有一个地方注意:- 对外发布编译文件时如果不希望被人看到源代码,可使用
go build -ldflags
命令。 - 设置参数【
-ldflags "-w -s"
】再编译发布,这样使用gdb
调试时无法看到源代码。
- 对外发布编译文件时如果不希望被人看到源代码,可使用
GO111MODULE
Go 1.11
新增了对模块的支持,希望借此解决“包依赖管理”问题。- 可以通过设置环境变量
GO111MODULE
来开启或关闭模块支持,它有三个可选值:off
、on
、auto
,默认值是auto
。GO111MODULE = off
- 无模块支持,
go
会从GOPATH
和vendor
文件夹寻找包。
- 无模块支持,
GO111MODEL = on
- 模块支持,
go
会从GOPATH
和vendor
文件夹,值根据go.mod
下载依赖。
- 模块支持,
GO111MODEL = auto
- 在
$GOPATH/src
外面且根目录有go.mod
文件时,开启模块支持。
- 在