包的导入
包
导入包
import
导入单个包
import "fmt" // 导入一个包
导入多个包(单语句,多行)
import (
"fmt"
"time" // 导入多个包
)
导入多个包(单语句,单行)可读性不好,不推荐
import ("fmt";"time") // 分号隔开
导入多个包(多语句)不常用,不推荐
import "fmt"
import "time"
不能重复导入
import "fmt"
import "fmt" // 重复导入,编译不过
包的初始化
init()
当一个包被import语句导入时,则会执行这个函数,执行顺序是按照包导入的顺序(有依赖包时先执行依赖包),源文件有多个init()函数时自上而下执行。
包别名
在程序中引用包时可以使用包的别名,设置别名之后原包名则不可用
设置别名格式如下:
import f "pkg/test" // 设置别名为 f
f.test() // 使用别名
.
import . "pkg/test"
test() // 直接调用,无需使用包名
_
import _ "pkg/test" // 不会导入包
自定义包
import "demo1/server"server目录名import "demo1/server"包名
示例:
包名与目录名一致(都为server)
package main
import "demo1/server" //导入包 server
func main(){
server.Test() // 此处的server为包名,调用包server的函数Test()
}
包名与目录名不一致(包名为srv, 目录名为server)
package main
import "demo1/server" // 导入包srv
func main(){
srv.Test() // 此处的srv为包名,调用包srv的函数Test()
}
go语言的这个特点为包的命名提供了灵活性,但是如果包名与目录名不一致,则代码库的可理解性会很差,在不知道被导入源码的情况下很难通过import语句得知包名,程序的可读性很差。
因此包的自定义最好要遵循一下原则:
- 一个目录下只能定义一个包(语法要求)
- 一个包只能定义在同一个目录下(go认为不同目录下的包不是同一个包)
- 包名和目录名相同(语法不强制,但强烈建议)
标准库中都遵循以上原则,自定义的库最好也要遵循这个原则,否则自定义库不容易使用。
包的管理
对于一个项目来说,go中的包无非有三种:
- 标准库的包,存在与$GOROOT/src
- 自定义库,每个项目都会有多个*.go文件组成,会形成本项目的自定义包,位于项目目录下
- 第三方包,一般是开源的或者公司内部的工具包,它可能会被多个项目用到
包的管理
基于GOPATH的包管理
导入路径
import
go找包的顺序:
import ./module
go get
项目管理
GOPATH下一般有三个目录:
目录 | 作用 |
---|---|
$GOPATH/bin/ | go install [package] 会将可执行文件放在此处 |
$GOPATH/pkg/ | 存放go build 生成的二进制对象(*.a文件等) |
$GOPATH/src/ | 存放源码。项目工程代码、第三方代码 |
基于此,项目工程的组织管理形式可以有多种,但必须都位于$GOPATH/src/目录下:
- 在$GOPATH/src/下直接放置项目工程,适用于个人的简单Demo项目
- 在$GOPATH/src/下通过域名组织项目,适用于开源项目。比如github上的go-cache项目,项目链接为https://github.com/patrickmn/go-cache,go get下载到本地的位置是$GOPATH/src/github.com/patrickmn/go-cache/,按照项目链接组织第三方包,方便go get自动保存包,并避免命名冲突。
3. 对于企业可以通过以下方式组织项目,企业一般在内网使用gitlab管理代码,可以按照以下方式,或者在此基础调整。
这种早期的基于GOPATH的项目管理方式有很多缺点:
- 项目必须放在$GOPATH/src/目录下,想在其他位置新建项目就得修改GOPATH变量,不方便。
- 如果不同的项目引用相同的包/模块,其中一个项目如果修改了这个模块,那么会影响其他项目。
- 不支持的模块的版本管理,如果不同的项目依赖了同一个模块的不同版本,切换项目时就要同时切换版本,如果依赖的模块很多,这事就比较麻烦了
基于GOPATH和vendor的包管理
为了解决单纯依赖GOPATH管理项目的问题,go v1.6版本正式支持了vendor管理机制,我们可以在项目工程目录下创建一个vendor目录,如下结构:
导入路径
有了vendor机制,包的导入路径有所变化,按照以下顺序查找:
vendorvendorsrcvendor
项目管理
项目的组织形式仍然同前述,只是在项目内部可以有自己的依赖包。但是仍然没有完全解决前述问题,因为如果两个项目中不同的依赖包又同时依赖了同一个第三方包(工程项目大了出现概率很大),则依然会出现前述问题。
基于go mod的包管理
1.11版本引入go mod,它可以彻底解决前述问题,启用go mod需要设置环境变量GO111MODULE,设置如下:
- on 开启go mod
- off 关闭go mod
- auto自动,在 $GOPATH/src 外面且根目录有 go.mod 文件时,开启模块支持
导入路径
go mod init {projectName}go.mod
go.mod文件格式如下
module github/zha/test
go 1.14
require (
github.com/patrickmn/go-cache v0.0.1 // indirect
github.com/aaa/go-test2 v0.0.0-20220605072926-e977b358c1c3 // indirect
)
replace (
golang.org/x/crypto => github.com/golang/crypto latest
github.com/patrickmn/go-cache => 本地项目包的地址
)
解释:
库名 版本号v*.*.* targetPkg => replacePkg
require项目名
go mod vendor
项目管理
go mod 支持项目工程的目录不一定要放在$GOPATH/src/ 下,放在任何地方均可;引用的第三方包则放在$GOPATH/pkg/mod/下;自定义包放在工程目录中。