您现在的位置是:网站首页> Go语言
Go go.mod使用
- Go语言
- 2022-03-17
- 980人已阅读
重要的环境变量GOROOT也就是Go的安装目录如"c:\Go" 还有GOPATH也就是包搜索工作空间目录,默认会去搜索定义的工作空间目录下的src和go安装目录下的src
通常设置的Go工作空间比如Hello,你在工作空间创建项目HelloA,其实HelloA所在目录为Hello\src\HelloA\...
不使用.mod文件记得将.env环境文件加一行
GO111MODULE=auto获得GO111MODULE=off
在liteide中工具-》编辑当前环境
当报错没有.mod文件时候生成.mod文件
明令行:
如go Module Init HelloJson
在开发环境里直接用菜单初始化如下
也可以
编译菜单里选择Go Module Init
golang 报错 missing go.sum entry 可以使用命令 go mod tidy 修复
go 1.13提供了 go env -w命令来写环境变量,这是用户级别的环境变量,像GO111MODULE、GOPROXY之类的可写的环境肯定是有持久化的,那么保存路径在哪儿呢?有一个env文件:
windows: 用户目录\AppData\Roaming\go\env
linux: /root/.config/go/env 可能是用root用户安装的,其他用户安装的可以看看 home目录下的 .config/go/env
如何使用go.mod?
1、确保go版本为1.11或更高
本文go版本号为1.16.3
2、开启gomodule
go env -w GO111MODULE=on
1
3、设置goproxy
使用国内代理提高依赖包下载速度
go env -w GOPROXY=https://goproxy.cn
1.首先将go的版本升级为1.11以上
2.设置GO111MODULE
GO111MODULE
GO111MODULE有三个值:off, on和auto(默认值)。
GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。
GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查找。
GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
当前目录在GOPATH/src之外且该目录包含go.mod文件
当前文件在包含go.mod文件的目录下面。
go.mod 文件内提供了module
, require
、replace
和exclude
四个关键字
module语句指定包的名字(路径)
require语句指定的依赖项模块
replace语句可以替换依赖项模块
exclude语句可以忽略依赖项模块
indirect:表示间接依赖
indirect
indirect 总是出现在require指令中,表示这个包是被间接依赖的 // 表示注释的开始,例如:
require (
github.com/google/uuid v1.3.0 // indirect
)
go.mod 文件中使用 indirect 关键字,告诉 Go 模块系统这个依赖项是间接的,不需要自动更新。
使用 indirect 关键字的常见场景是,当你的项目依赖于某个模块,但你只是为了传递依赖关系,而不直接使用该模块。这样可以避免不必要的模块下载和更新,减少构建过程的复杂性和时间。
Go Mod命令详解
1. init
go mod init生成mod文件
2.download
go mod download 下载 go.mod 文件中指明的所有依赖,使用此命令来下载指定的模块,模块的格式可以根据主模块依赖的形式或者path@version形式指定。
3.tidy
go mod tidy
整理现有的依赖,使用此命令来下载指定的模块,并删除已经不用的模块
4.graph
go mod graph
查看现有的依赖结构,生成项目所有依赖的报告,但可读性太差,图形化更方便。
5.edit
go mod edit
编辑 go.mod 文件,之后通过 download 或 edit 进行下载
6.vendor
go mod vendor
导出项目所有的依赖到vendor目录,从mod中拷贝到项目的vendor目录下,IDE可以识别这样的目录。
7.verify
go mod verify
校验一个模块是否被篡改过,查询某个常见的模块出错是否已被篡改
8.why
go mod why
查看为什么需要依赖某模块,查询某个不常见的模块是否是哪个模块的引用
我们将ddis指向本地包所在的目录,可以是相对路径,也可以是绝对路径
replace (
ddis => D:\GoShareLib\trunk\ddis
)
此处是不需要携带版本号的,完成上述操作之后,我们就可以直接在代码中调用本地包了
import (
"ddis"
)
在golang中,开启mod模式后,import包变红,但是程序可以正常运行
下面是我们建立了一个hello.go的文件
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, world!")
}
当前目录下,命令行运行 go mod init + 模块名称 初始化模块
即go mod init hello
运行完之后,会在当前目录下生成一个go.mod文件,这是一个关键文件,之后的包的管理都是通过这个文件管理。
官方说明:除了go.mod之外,go命令还维护一个名为go.sum的文件,其中包含特定模块版本内容的预期加密哈希
go命令使用go.sum文件确保这些模块的未来下载检索与第一次下载相同的位,以确保项目所依赖的模块不会出现意外更改,无论是出于恶意、意外还是其他原因。 go.mod和go.sum都应检入版本控制。
go.sum 不需要手工维护,所以可以不用太关注。
注意:子目录里是不需要init的,所有的子目录里的依赖都会组织在根目录的go.mod文件里
接下来,让我们的项目依稀一下第三方包
如修改hello.go文件如下,按照过去的做法,要运行hello.go需要执行go get 命令 下载gorose包到 $GOPATH/src
package main
import (
"fmt"
"github.com/gohouse/gorose"
)
func main() {
fmt.Println("Hello, world!")
}
但是,使用了新的包管理就不在需要这样做了
直接 go run hello.go
稍等片刻… go 会自动查找代码中的包,下载依赖包,并且把具体的依赖关系和版本写入到go.mod和go.sum文件中。
查看go.mod,它会变成这样:
module test
require (
github.com/gohouse/gorose v1.0.5
)
require 关键字是引用,后面是包,最后v1.11.1 是引用的版本号
这样,一个使用Go包管理方式创建项目的小例子就完成了。
问题一:依赖的包下载到哪里了?还在GOPATH/src里吗?
不在。
使用Go的包管理方式,依赖的第三方包被下载到了$GOPATH/pkg/mod路径下。
问题二: 依赖包的版本是怎么控制的?
在上一个问题里,可以看到最终下载在$GOPATH/pkg/mod 下的包中最后会有一个版本号 v1.0.5,也就是说,$GOPATH/pkg/mod里可以保存相同包的不同版本。
版本是在go.mod中指定的。如果,在go.mod中没有指定,go命令会自动下载代码中的依赖的最新版本,本例就是自动下载最新的版本。如果,在go.mod用require语句指定包和版本 ,go命令会根据指定的路径和版本下载包,
指定版本时可以用latest,这样它会自动下载指定包的最新版本;
问题三: 可以把项目放在$GOPATH/src下吗?
可以。但是go会根据GO111MODULE的值而采取不同的处理方式,默认情况下,GO111MODULE=auto 自动模式
1.auto 自动模式下,项目在$GOPATH/src里会使用$GOPATH/src的依赖包,在$GOPATH/src外,就使用go.mod 里 require的包
2.on 开启模式,1.12后,无论在$GOPATH/src里还是在外面,都会使用go.mod 里 require的包
3.off 关闭模式,就是老规矩。
问题三: 依赖包中的地址失效了怎么办?比如 golang.org/x/… 下的包都无法下载怎么办?
在go快速发展的过程中,有一些依赖包地址变更了。以前的做法:
1.修改源码,用新路径替换import的地址
2.git clone 或 go get 新包后,copy到$GOPATH/src里旧的路径下
无论什么方法,都不便于维护,特别是多人协同开发时。
使用go.mod就简单了,在go.mod文件里用 replace 替换包,例如
replace golang.org/x/text => github.com/golang/text latest
这样,go会用 github.com/golang/text 替代golang.org/x/text,原理就是下载github.com/golang/text 的最新版本到 $GOPATH/pkg/mod/golang.org/x/text下。
问题四: init生成的go.mod的模块名称有什么用?
本例里,用 go mod init hello 生成的go.mod文件里的第一行会申明module hello
因为我们的项目已经不在$GOPATH/src里了,那么引用自己怎么办?就用模块名+路径。
例如,在项目下新建目录 utils,创建一个tools.go文件:
package utils
import “fmt”
func PrintText(text string) {
fmt.Println(text)
}
在根目录下的hello.go文件就可以 import “hello/utils” 引用utils
package main
import (
"hello/utils"
"github.com/astaxie/beego"
)
func main() {
utils.PrintText("Hi")
beego.Run()
}
问题五:以前老项目如何用新的包管理
如果用auto模式,把项目移动到$GOPATH/src外
进入目录,运行 go mod init + 模块名称
go build 或者 go run 一次
按原来方式创建好项目,然后初始化出.mod文件也就是执行命令行 Go Module Init 主文件名
如go Module Init HelloJson
在开发环境里直接用菜单初始化如下
生成文件go.mod文件如下
module github.com/xuneng/hellojson /*这个表示目前项目包是github.com/xuneng/hellojson,不是直接到Go目录下去找该包的文件,是在本项目目录下查找,发布之后是github.com/xuneng/hellojson*/
go 1.13
require (
github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/go-redis/redis/v7 v7.2.0
github.com/gorilla/mux v1.7.4 // indirect
github.com/kr/pretty v0.1.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/satori/go.uuid v1.2.0
github.com/sirupsen/logrus v1.5.0
github.com/spf13/pflag v1.0.3
github.com/spf13/viper v1.6.3
github.com/stretchr/testify v1.4.0
github.com/urfave/negroni v1.0.0 // indirect
)
正式的livego的mod文件:
module github.com/gwuhaolin/livego
go 1.13
require (
github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/go-redis/redis/v7 v7.2.0
github.com/gorilla/mux v1.7.4 // indirect
github.com/kr/pretty v0.1.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/satori/go.uuid v1.2.0
github.com/sirupsen/logrus v1.5.0
github.com/spf13/pflag v1.0.3
github.com/spf13/viper v1.6.3
github.com/stretchr/testify v1.4.0
github.com/urfave/negroni v1.0.0 // indirect
)
在 Go 语言的模块(module)文件(go.mod)中,+incompatible 是一个特殊的修饰符,用于处理与兼容性相关的模块版本问题。它通常在模块的版本号后面使用,用于指示该版本与先前版本不兼容。
在 Go 模块系统中,每个模块都有一个唯一的版本号,以便其他模块可以明确地依赖于该版本。当一个模块的 API 发生重大变化,不再与先前版本兼容时,开发人员可以选择在模块版本号后面添加 +incompatible 标记来表示这种不兼容性。
使用 +incompatible 的目的是为了与旧版本的模块保持向后兼容。当你需要升级一个模块,并且新版本与先前版本不兼容时,可以使用 +incompatible 标记来指示模块管理工具(如 Go Modules)在解析依赖关系时允许使用不兼容的版本。
使用方法如下:
在你的 go.mod 文件中,将模块的版本号后面添加 +incompatible 标记,例如:
module example.com/myapp/v2
go 1.16
require (
example.com/mymodule v2.0.0+incompatible
)
在引入该模块时,使用带有 +incompatible 标记的版本号,例如:
import (
"example.com/mymodule/v2"
)
需要注意的是,+incompatible 标记是一种权宜之计,应该尽量避免使用。它适用于那些真正需要破坏向后兼容性的情况,例如重构或重大架构更改。在大多数情况下,应该尽量保持模块的向后兼容性,并使用合适的语义版本控制来管理模块的演进。
下一篇:实用代码下载