包是函数和数据的集合,将有相关特性的函数和数据放在统一的文件/目录进行管理,每个包都可以作为独立的单元维护并提供给其他项目进行使用

1. 声明

Go 源文件都需要在开头使用 package 声明所在包,包名告知编译器哪些是包的源代码用于编译库文件,其次包名用于限制包内成员对外的可见性,最后包名用于在包外对公开成员的访问
包名使用简短的小写字母,常与所在目录名保持一致,一个包中可以由多个 Go 源文件,但必须使用相同包名
image.png
声明两个包,路径分别为 gpkgname/pkg01 和 gpkgname/pkg02

2. 导入&调用

在使用包时需要使用 import 将包按路径名导入,再通过包名调用成员可通过 import 每行导入一个包,也可使用括号包含所有包并使用一个 import 导入
image.png
工作目录结构说明:

  • bin: 用于放置发布的二进制程序
  • pkg: 用于放置发布的库文件
  • src: 用于放置源代码

运行:
a) 将 chapter08/gv 目录添加到 GOPATH 环境变量中
b) 编译&运行

  • 使用 go build 编译二进制文件
    • 命令:go build gpkgmain
    • 说明:编译路径 gpkgmain 下的包,main 包,则在当前目录产生以 pkgmain 命名的
    • 二进制程序
  • 使用 go run 运行二进制文件
    • 命令:go run gpkgmain
  • 使用 go install 编译并发布二进制文件
    • 命令:go install gpkgmain
    • 说明:编译并发布路径 gpkgmain 下的包,main 包,则在将编译后的以 pkgmain 命名的二进制程序拷贝到 bin 目录
  • 使用 go install 编译发布库文件
    • 命令:go install gpkgname/pkg01
    • 说明:编译并发布路径 gpkgname/pkg01 下的包,非 main 包,则在将编译的以包名命名的库文件拷贝到 pkg/GOOS_GOARCH 目录下
  • 使用 go install 编译发布所有二进制和库文件

    • 命令:go install ./…
    • 说明:编译并发布当前路径下的所有二进制程序和库文件,注意:Go 语言不允许交叉导入包

      3. 导入形式

      1) 绝对路径导入

      GOPATH 目录中查找包
      示例:
  • import "fmt"

  • import "gpkgname/pkg01"

    2) 相对路径导入

    在当前文件所在的目录查找
    示例:import "./gpkgname/pkg02"

    3) 点导入

    在调用点导入包中的成员时可以直接使用成员名称进行调用(省略包名)
    image.png

    4) 别名导入

    当导入不同路径的相同包名时,可以别名导入为包重命名,避免冲突
    image.png

    5) 下划线导入

    Go 不允许包导入但未使用,在某些情况下需要初始化包,使用空白符作为别名进行导入,从而使得包中的初始化函数可以执行
    image.png

    4. 成员可见性

    Go 语言使用名称首字母大小写来判断对象(常量、变量、函数、类型、结构体、方法等)的访问权限,首字母大写标识包外可见(公开的),否者仅包内可访问(内部的)
    image.png

    5. main 包与 main 函数

    main 包用于声明告知编译器将包编译为二进制可执行文件
    在 main 包中的 main 函数是程序的入口,无返回值,无参数

    6. init 函数

    init 函数是初始化包使用,无返回值,无参数。建议每个包只定义一个。init 函数在 import包时自动被调用(const->var->init)
    image.png
    image.png
    image.png

    7. Go 包管理

    1) 介绍

    Go1.11 版本提供 Go modules 机制对包进行管理,同时保留 GOPATH 和 vendor 机制,使用临
    时环境变量 GO111MODULE 进行控制,GO111MODULE 有三个可选值:
    a) 当 GO111MODULE 为 off 时,构建项目始终在 GOPATH 和 vendor 目录搜索目标程序依赖包
    b) 当 GO111MODULE 为 on 时,构建项目则始终使用 Go modules 机制,在 GOPATH/pkg/mod目录搜索目标程序依赖包
    c) 当 GO111MODULE 为 auto(默认)时,当构建源代码不在 GOPATH/src 的子目录且包含go.mod 文件,则使用 Go modules 机制,否则使用 GOPATH 和 vendor 机制

    2) GOPATH+vendor 机制

    开启Go-mode

  • 设置GO111MODULE=on,开启gomode,不设置则不开启Gomode

  • 关闭Gomode:go env -w GO111MODULE=

a) vendor将项目依赖包拷贝到项目下的 vendor 目录,在编译时使用项目下 vendor 目录中的包进行编译
解决问题:

  • 依赖外部包过多,在使用第三方包时需要使用 go get 进行下载
  • 第三方包在 go get 下载后不能保证开发和编译时版本的兼容性

b) 包搜索顺序

  • 在当前包下的 vendor 目录查找
  • 向上级目录查找,直到 GOPATH/src/vendor 目录
  • 在 GOPATH 目录查找
  • 在 GOROOT 目录查找

c) 第三方包
可以借助 go get 工具下载和安装第三方包及其依赖,需要安装与第三方包匹配的代码管理工具,比如 git、svn 等
使用方法:
image.png
常用参数:

  • -d:仅下载依赖包
  • -u:更新包并安装
  • -x:打印执行的命令
  • -v:打印构建的包
  • -insecure:允许使用 http 协议下载包

第三方包查找地址:

  • https://godoc.org
  • https://gowalker.org/

    3) Go modules 机制

    a) 优势:

  • 不用设置 GOPATH,代码可任意放置

  • 自动下载依赖管理
  • 版本控制
  • 不允许使用相对导入
  • replace 机制

b) 初始化模块
命令:go mod init modname
image.png
c) 当前模块下的包
对于当前模块下的包导入时需要使用 modname+packagename
image.png
d) 第三方包
在使用 go mod tidy、go build、go test、go list 命令会自动将第三方依赖包写入到go.mod 文件中同时下载第三方依赖包到GOPATH/pkg/mod/cache 目录,并在当前模块目录生成一个构建状态跟踪文件 go.sum,文件中记录当前 module 所有的顶层和间接依赖,以及这些依赖的校验和
image.png
e) 常用命令

  • go mod tidy:整理依赖模块(添加新增的,删除未使用的)
  • go mod vendor: 将依赖模块拷贝到模块中的 vendor 目录
  • go build: 编译当前模块
  • go build ./…: 编译当前目录下的所有模块
  • go build -mod=vendor:使用当前模块下的 vendor 目录中的包进行编译
  • 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 功能将包替换为本地包,实现相对导入

    8. 标准包

    Go 提供了大量标准包,可查看:https://golang.google.cn/pkg/

    1) godoc 工具

    使用 godoc 命令可以在本地启动 golang 网站,用于本地查看帮助手册
    image.png

    2) 帮助

    a) go list std:查看所有标准包
    image.png
    b) go doc packagename:查看包的帮助信息
    image.png
    c) go doc packagename.element:查看包内成员帮助信息
    image.png