前言
Go Modules是Go语言的包管理工具,提供简洁可靠的依赖管理,解决了GOPATH和vendor目录的问题,使项目依赖更清晰易管理。要启用go module支持首先要设置环境变量GO111MODULE,通过它可以开启或关闭模块支持,它有三个可选值:off、on、auto,默认值是auto。设置GO111MODULE=on之后就可以使用go module了,以后就没有必要在GOPATH中创建项目了,并且还能够很好的管理项目依赖的第三方包信息。
命令
- GO111MODULE=off 禁用模块支持,编译时会从GOPATH和vendor文件夹中查找包。
- GO111MODULE=on 启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据 go.mod下载依赖。
- GO111MODULE=auto 当项目在$GOPATH/src外且项目根目录有go.mod文件时,开启模块支持。
sh
go env -w GO111MODULE=on 设置GO111MODULE
go env set GO111MODULE 查看GO111MODULE环境变量
go env 查看所有环境变量
使用
go的项目也是一个单独包 初始化一个项目,新建一个 demo文件夹,执行命令
go mod init demo
会生成一个 go.mod 文件 新建一个main.go 作为程序入口文件
sh
└── demo
├── go.mod
└── main.go
go
package main
func main() {
}
yaml
package main
func main() {
}
使用下载包
使用 go get 下载
go
└── demo
├── utils
│ └── hello.go
├── go.mod
├── go.sum
└── main.go
sh
go get go.uber.org/zap
在 main.go 中使用
go
package main
import (
"go.uber.org/zap"
)
func main() {
zapLog, _ := zap.NewProduction()
zapLog.Info("failed to fetch URL")
}
go.mod
yaml
module demo
go 1.19
require (
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/zap v1.27.0 // indirect
)
require 引用依赖包及版本 indirect 表示间接引用
导入项目子文件的包
新建 utils 文件夹和 hello.go文件
go
└── demo
├── utils
│ └── hello.go
├── go.mod
├── go.sum
└── main.go
hello.go 内容
go
package utils
import "fmt"
func Hello() {
fmt.Println("hello world")
}
在main中使用
go
package main
import "main/utils"
func main() {
pkg2.Hello()
}
导入本地包
demo 同级目录下创建一个 pkg 包
go
├── demo
│ ├── utils
│ │ └── hello.go
│ ├── go.mod
│ ├── go.sum
│ └── main.go
└── pkg
├── go.mod
└── hello.go
- 初始化pkg包 go mod init pkg
- 在 pkg2 目录新建 hello.go文件
go
package pkg
import "fmt"
func PkgHello() {
fmt.Println("PkgHello:hello world")
}
- 在 demo main里面调用
go
package main
import "pkg2"
func main() {
pkg2.Hello()
}
你会发现报错
could not import pkg2 (no required module provides package "pkg2")
因为这两个包不在同一个项目路径下,你想要导入本地包,并且这些包也没有发布到远程的github或其他代码仓库地址。这个时候我们就需要在go.mod文件中使用replace指令。
- 修改
pkg1
下的go.mod文件
sh
module demo
go 1.19
require (
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/zap v1.27.0 // indirect
pkg2 v0.0.0
)
replace pkg2 => ../pkg2
go run main.go 运行是否正常
- replace 替换包的地址
注意
注意需要引入的函数和变量首字母需要大写 封装机制 包是不能互相引入的就会形成循环导入go语言是禁止的
Go 语言的封装机制大小写机制
如果以大写字母开头,表示该标识符是公开的,可以被其他包引用 如果以小写字母开头,表示该标识符是私有的,只能在定义它的包中使用,其他包无法直接引用 变量命 函数名 类型名 属性名 都需要需要遵循
go
var One = 1
var two = 2
func OneFn(){}
func twoFn(){}
type OneType struct {
Name string // 公开字段
age int // 私有字段
}
type twoType struct {
Name string // 公开字段
age int // 私有字段
}
One OneFn OneType 可以被引用 但是OneType中的age字段不能正常使用
u := pkg.OneType{Name: "xx"}
小写的为私有只能在定义它们的包中使用
作用域
go
package main
import "fmt"
// 包级作用域 全局作用域 区别在于是不是主文件
var globalVar = "This is a global variable"
func main() {
// 函数级作用域
var localVar = "This is a local variable"
// 块级作用域
{
blockVar := "This is a block variable"
fmt.Println(localVar) // 可以访问函数级作用域内的变量
fmt.Println(blockVar) // 可以访问块级作用域内的变量
}
fmt.Println(globalVar) // 可以访问包级作用域内的变量
// fmt.Println(blockVar) // 编译错误,无法访问块级作用域外的变量
}
扩展
熟悉 go module 的命令
sh
go mod help 展示所有命令
go mod download 下载依赖的module到本地cache(默认为$GOPATH/pkg/mod目录)
go mod edit 编辑go.mod文件 (--fmt 格式化)
go mod graph 打印模块依赖图
go mod init 初始化当前文件夹, 创建go.mod文件
go mod tidy 增加缺少的module,删除无用的module
go mod vendor 将依赖复制到vendor下
go mod verify 校验依赖
go mod why 解释为什么需要依赖
熟悉 go mod 文件的一些关键字
- module 用来定义包名
- go 1.19 当前go的版本
- require 用来定义依赖包及版本
- indirect 表示间接引用
- replace 替换包的地址
包下载 get get
使用下载包的前提是需要了解两个命令
go get
和go install
go get命令可以下载依赖包,并且还可以指定下载的版本
- 运行go get -u将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
- 运行go get -u=patch将会升级到最新的修订版本
- 运行go get package@version将会升级到指定的版本号version
2024/3/5 ⛅