Go语言是使用包来组织源代码的,包(package)是多个 Go 源码的集合,是一种高级的代码复用方案。Go语言中为我们提供了很多内置包,如 fmt、os、io 等。
任何源代码文件必须属于某个包,同时源码文件的第一行有效代码必须是package pacakgeName
语句,通过该语句声明自己所在的包。
Go语言的包借助了目录树的组织形式,一般包的名称就是其源文件所在目录的名称,虽然Go语言没有强制要求包名必须和其所在的目录名同名,但还是建议包名和所在目录同名,这样结构更清晰。
包可以定义在很深的目录中,包名的定义
是不包括目录路径的,但是包在引用时一般使用全路径引用。
包名小写字母,尽量短小。
包名一般要和所在的目录同名,也可以不同,包名中不能包含`-` 等特殊符号。
同一个文件夹所有go文件的包名必须一致
包名为 main 的包为应用程序的入口包,编译不包含 main 包的源码文件时不会得到可执行文件。
import "包1的路径"
import "包2的路径"
import (
"包 1 的路径"
"包 2 的路径"
)
此时可以用fmt.
作为前缀来使用 fmt 包中的方法,这是常用的一种方式。
import "fmt"
import F "fmt"
其中 F 就是 fmt 包的别名,使用时我们可以使用F.
来代替标准引用格式的fmt.
来作为前缀使用 fmt 包中的方法。
import . "fmt"
不用加前缀fmt.
,直接引用。
使用标准格式引用包,但是代码中却没有使用包,编译器会报错。如果包中有 init
初始化函数,则通过import _ "包的路径"
这种方式引用包,仅执行包的初始化函数,即使包没有 init 初始化函数,也不会引发编译器报错。
import _ "fmt"
匿名导入的包与其他方式导入的包一样都会被编译到可执行文件中。
注意:
(1)一个包可以有多个 init 函数,包加载时会执行全部的 init 函数,但并不能保证执行顺序,所以不建议在一个包中放入多个 init 函数,将需要初始化的逻辑放到一个 init 函数里面。
(2)包不能出现环形引用的情况,比如包 a 引用了包 b,包 b 引用了包 c,如果包 c 又引用了包 a,则编译不能通过。
(3)包的重复引用是允许的,比如包 a 引用了包 b 和包 c,包 b 和包 c 都引用了包 d。这种场景相当于重复引用了 d,这种情况(有向无环图)是允许的,并且 Go 编译器保证包 d 的 init 函数只会执行一次。
在执行 main 包的 mian 函数之前, Go 引导程序会先对整个程序的包进行初始化。整个执行的流程如下图所示:
GOPATH环境变量、配置目录、项目开发目录
工作目录结构说明:
bin: 用于放置发布的二进制程序
pkg: 用于放置库文件,非main包编译结果
src: 用于放置源代码
包的绝对路径就是GOROOT/src/
或GOPATH/src/
或者gomod
后面包的存放路径,现在一般使用gomod
的方式
// GOPATH/src/database目录路径引用
// GOPATH/src/lab目录路径引用
import "lab/test"
import "database/sql/driver"
import "database/sql"
import "./gpkgname/pkg02"
GOPATH/src/pakeage
go build 编译二进制文件
go build GOPATHMAIN
编译路径GOPATH下的包main包,则在当前目录产生以GOPATHMAIN命名的二进制程序
go run 运行二进制文件
go install 编译并发布二进制文件
go install GOPATHMAIN
编译并发布路径GOPATHMAIN下的包,main包,则在将编译后的以GOPATHMAIN命名的二进制程序拷贝到bin目录
go install 编译发布库文件
go install GOPATHMAIN/pkg01
编译并发布路径GOPATHMAIN/pkg01下的包,非main包,则在将编译的以包名命名的库文件拷贝到 pkg/GOOS_GOARCH目录下
go install 编译发布所有二进制和库文件
go install ./…
编译并发布当前路径下的所有二进制程序和库文件,不允许交叉导入包
go 1.5版本推出的vendor
GOPATH项目目录下创建vendor目录 第三方包将下载拷贝到vendor
当前a包中使用顺序
a/vendor
a/../vendor
GOPATH/src/vendor
GOPATH/src
GOROOT/src
升级需要覆盖旧的vendor,不方便管理。所以go 1.11出现了go mod管理方式
可以借助 go get 工具下载和安装第三方包及其依赖,需要安装与第三方包匹配的代码管理工具,比如 git、svn 等
常用参数:
-d:仅下载依赖包
-u:更新包并安装
-x:打印执行的命令
-v:打印构建的包
-insecure:允许使用 http 协议下载包
第三方包查找地址:
go 1.11推出了go modules机制
不用设置 GOPATH,代码可任意放置
自动下载依赖管理
版本控制
不允许使用相对导入
replace 机制
go env -w GO111MODULE=on
GO111MODULE=off 无模块支持,go 会从 GOPATH 和 vendor 文件夹寻找包。必须GOPATH
GO111MODULE=on 模块支持,go 会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod 下载依赖。必须go.mod
GO111MODULE=auto 自动选择,在 $GOPATH/src 外面且根目录有 go.mod 文件时,开启模块支持。否则使用 GOPATH 和 vendor 机制
go mod init modname
import (
"fmt"
"modname/math"
"modname/math/pkgb"
) // 模块名称/目录路径!!!
导入包顺序
1、go标准包
2、第三方包
3、本地包
包4种引用格式
在使用 go mod tidy(整理模块)、go build(编译当前模块)、go test、go list 命令会自动将第三方依赖包写入到go.mod 文件中同时下载第三方依赖包到 GOPATH/pkg/mod/cache目录,并在当前模块目录生成一个构建状态跟踪文件 go.sum,文件中记录当前 module 所有的顶层和间接依赖,以及这些依赖的校验和
go.mod文件方式
module testmod
go 1.14
replace (
golang.org/x/net => github.com/golang/net v0.0.0-20180906233101-161cd47e91fd
)
命令行方式
go mod edit -replace=goland.org/x/net@latest=github.com/goland/net@latest // 编写代码还是goland,实际是github
go.mod文件
module testmod
go 1.14
replace (
golang.org/x/net => github.com/golang/net v0.0.0-20180906233101-161cd47e91fd
)
require (
github.com/astaxie/beego v1.12.2 // indirect
github.com/imsilence/testmath v0.0.0-20201017035600-785fc3eb6ad9
) // 查看go.mod文件中自动添加的第三方模块和go.sum文件
go.sum文件
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
省略...
go mod tidy: 精简不依赖的库
go mod vendor: 将依赖模块拷贝到模块中的 vendor 目录,使用vender方式
go build: 编译当前模块
go build ./...: 编译当前目录下的所有模块
go build -mod=vendor: 使用当前模块下的 vendor 目录中的包进行编译
go mod edit : 编辑go.mod文件
go mod download: 仅下载第三方模块
go mod grapha: 打印所有第三方模块
go list -m -json all:显示所有模块信息
go mod edit: 修改 go.mod 文件
? -require=pakcage@version
? -replace=old_package@version=new_package@version
? 可以使用-replace 功能将包替换为本地包,实现相对导入
gitlab/gitee
1. 自己内网程序, 没有以来任何第三方库
2. 依赖内部其他团队提供的库
3. 依赖外网的第三方库
a. 编译环境 => 目标站点
=> acl
=> proxy <=> 镜像
=> 第三方包下载 => gitlab/gitee
replace
首字母大写(变量和函数),包外可见
首字母小写(变量和函数),只能包内使用
因为:
导入包:项目名称/目录
用包:包名.方法
原文:https://www.cnblogs.com/Otiger/p/13889004.html