Go语言是使用包来组织源代码的,包(package)是多个 Go 源码的集合,是一种高级的代码复用方案。Go语言中为我们提供了很多内置包,如 fmt、os、io 等。
任何源代码文件必须属于某个包,同时源码文件的第一行有效代码必须是package pacakgeName
语句,通过该语句声明自己所在的包。
GOPATH/src/a/b/
下定义一个包c
。在包 c 的源码中只需声明为package c
,而不是声明为package a/b/c
,但是在导入 c 包时,需要带上路径,例如import "a/b/c"
-
等特殊符号。%GOPATH%/src/github.com/userName/projectName
目录下。//单行导入
import "fmt"
//多行导入
import(
"fmt"
"os"
)
根目录是GOPATH/src/
import "lab/test"
import "database/sql/driver"
相对路径只能用于导入GOPATH
下的包,标准包的导入只能使用全路径导入。
相对于当前包所在路径
import "../a"
在Golang中,一个包下存在多个源文件,若要在某个源文件中引入其他源文件声明的函数、结构体、全局变量等成员,引用规则如下:
成员名称
引用包名.成员名称
进行引用internal
包以及其子包中成员仅能在internal
的父级包或兄弟包中引用。例如有项目结构如下
- controller
- c1.go
- c2.go
- main.go
- go.mod
go.mod
module top.ygang/demo
go 1.21.5
c1.go
package controller
var Contro1Variable int
func Contro1() {
}
c2.go
package controller
func Contro2() {
Contro1()
}
main.go
package main
import "top.ygang/demo/controller"
func main() {
controller.Contro1()
controller.Contro2()
controller.Contro1Variable = 10
}
直接使用包名来引用
import "fmt"
fmt.Println("hello")
一般用于引用了两个同名包时区分使用
import F "fmt"
F.Println("hello")
把 fmt 包直接合并到当前程序中,在使用 fmt 包内的方法是可以不用加前缀fmt.
,直接引用
import . "fmt"
Println("hello")
在引用某个包时,如果只是希望执行包初始化的 init
函数,而不使用包内部的数据时,可以使用匿名引用格式
import _ "fmt"
import _ "包的路径"
这种方式引用包,仅执行包的初始化函数,即使包没有 init 初始化函数,也不会引发编译器报错。Go语言包的初始化有如下特点:
封装的好处:
如何体现封装:
封装的实现步骤:
init()
函数会在每个包完成初始化后自动执行,并且执行优先级比main函数高。init()
函数通常被用来:
init()
函数无参数、无返回值
func init(){
}
注意:一个包中可以包含多个init()
函数,但是执行顺序无法确认,所以不建议这么做!
最初的时候Go语言所依赖的所有的第三方包都放在 GOPATH 目录下面,这就导致了同一个包只能保存一个版本的代码
注意:该方式现已不推荐使用,原因:放弃了依赖重用,使得冗余度上升。同一个依赖包如果不同工程想重用,都必须各自复制一份在自己的vendor
目录下。
godep 是一个Go语言官方提供的通过 vender 模式来管理第三方依赖的工具,类似的还有由社区维护的准官方包管理工具 dep。
Go语言从 1.5 版本开始开始引入 vendor 模式,如果项目目录下有 vendor 目录,那么Go语言编译器会优先使用 vendor 内的包进行编译、测试等。
go module 是Go语言从 1.11 版本之后官方推出的版本管理工具,项目就不需要再放到GOPATH
下了,并且从 Go1.13 版本开始,go module 成为了Go语言默认的依赖管理工具。
GOMODULE
模式和GOPATH
模式一样都指定了依赖包存放的位置,而不是如vendor模式放入工程内,区别在于GOMODULE的go.mod
文件中记录了所依赖包的具体版本,既实现了工程之间重用依赖包,且解决了GOPATH
模式下不同工程无法依赖同一个包的不同版本的问题。
在Go语言 1.12 版本之前,要启用 go module 工具首先要设置环境变量 GO111MODULE
,不过在Go语言 1.13 及以后的版本则不再需要设置环境变量。通过 GO111MODULE
可以开启或关闭 go module 工具。
GO111MODULE=off
:禁用 go module,编译时会从 GOPATH 和 vendor 文件夹中查找包。GO111MODULE=on
:(1.16后默认值) 启用 go module,编译时会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod
下载依赖。GO111MODULE=auto
:(1.16前默认值),当项目在 GOPATH/src
目录之外,并且项目根目录有 go.mod
文件时,开启 go module。Windows 下开启 GO111MODULE
的命令为:
set GO111MODULE=on
#或者
set GO111MODULE=auto
MacOS 或者 Linux 下开启 GO111MODULE
的命令为:
export GO111MODULE=on
#或者
export GO111MODULE=auto
使用 go module 的go mod init projectname
命令后会在当前目录下生成一个go. mod
文件,并且在编译/运行当前目录下代码或者使用go get
命令的时候会在当前目录下生成一个 go.sum
文件。
go.mod
文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get
、go build
、go mod
等修改和维护go.mod
文件。
go.mod
文件记录了项目所有的依赖信息,其结构大致如下:
module demo
go 1.13
require (
github.com/astaxie/beego v1.12.0
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
)
go.mod 文件内提供了module、require、replace和exclude四个关键字。
// indirect
说明这个依赖是间接依赖,标记为间接的依赖与没标记的在功能上并没有差别,只是供查看go.mod
文件的人查看使用。go.sum 文件则是用来记录每个依赖包的版本及哈希值,如下所示:
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM=
github.com/astaxie/beego v1.12.0 h1:MRhVoeeye5N+Flul5PoVfD9CslfdoH+xqC/xvSQ5u2Y=
github.com/astaxie/beego v1.12.0/go.mod h1:fysx+LZNZKnvh4GED/xND7jWtjCR6HzydR2Hh2Im57o=
命令 | 作用 |
---|---|
go mod download | 下载依赖包到本地(默认为 GOPATH/pkg/mod 目录) |
go mod edit | 编辑 go.mod 文件 |
go mod graph | 打印模块依赖图 |
go mod init | 初始化当前文件夹(项目),创建 go.mod 文件 |
go mod tidy | 增加缺少的包,删除无用的包 |
go mod vendor | 将依赖复制到 vendor 目录下 |
go mod verify | 校验依赖 |
go mod why | 解释为什么需要依赖 |
go get
命令用于从远程代码仓库(比如 Github )上下载并安装代码包。
注意:如果GO111MODULE=on
或者auto
,在go get
下载包时候,会下载到GOPATH/pkg/mod
,引入时也是同样的从这个目录开始;如果运行了go env -w GO111MODULE=off
,那么在go get
下载包时候,会下载到GOPATH/src
目录下
常用命令标记:
-d # 让命令程序只执行下载动作,而不执行安装动作。
-f # 仅在使用-u标记时才有效。该标记会让命令程序忽略掉对已下载代码包的导入路径的检查。如果下载并安装的代码包所属的项目是你从别人那里 Fork 过来的,那么这样做就尤为重要了。
-fix # 让命令程序在下载代码包后先执行修正动作,而后再进行编译和安装。
-insecure # 允许命令程序使用非安全的 scheme(如 HTTP )去下载指定的代码包。如果你用的代码仓库(如公司内部的 Gitlab )没有HTTPS 支持,可以添加此标记。请在确定安全的情况下使用它。
-t # 让命令程序同时下载并安装指定的代码包中的测试源码文件中依赖的代码包。
-u # 让命令利用网络来更新已有代码包及其依赖包。默认情况下,该命令只会从网络上下载本地不存在的代码包,而不会更新已有的代码包。
go get -u
命令会将项目中的包升级到最新的次要版本或者修订版本;go get -u=patch
命令会将项目中的包升级到最新的修订版本;go get [包名]@[版本号]
命令会下载对应包的指定版本或者将对应包升级到指定的版本。
go get [包名]@[版本号]
命令中版本号可以是x.y.z
的形式,例如go get foo@v1.2.3
,也可以是 git 上的分支或 tag,例如go get foo@master
,还可以是 git 提交时的哈希值,例如go get foo@e3702bed2
。
第三方包查询:https://pkg.go.dev/