日常开发离不开第三方库,大部分的时候,这些库都是满足咱们的须要,但有的时候,咱们须要 fork 一份,做一些批改。go mod 作为以后 go 语言的官网包管理器,天然也思考到了这种状况。在 go.mod 文件中,通过 replace 指令,将旧的库地址,替换为新的库地址来实现这一操作。
上面通过一个示例来解说 go replace 的应用,以及常见问题的解决。
咱们首先新建一个我的项目,并在其中援用 ozgio/strutil: String utilities for Go (github.com) 这个字符串解决库,而后轻易写段代码,确保其能够失常工作:
package main
import (
"fmt"
"github.com/ozgio/strutil"
)
func main() {fmt.Println(strutil.Align("lorem ipsum", strutil.Right, 20))
}
go mod 的初始化
go mod init project_name
go mod init 命令执行后,会主动生成 go.mod
文件,该文件中,列出了我的项目所依赖的第三方包,以及所应用的版本。
而后执行 go mod tidy
,该命令做两件事:
- 解析我的项目文件,并找到所应用的包
- 生成 go.sum 文件,其中保留了所应用包的版本
而后执行 go run main.go
,来执行我的项目。
当初,我的项目应该曾经能够失常执行,并返回执行后果了。
假如咱们此时想调用一个过滤字符串中,HTML 标签的办法,但翻了一下并没有,于是 fork 了一份这个库,咱们本人增加了进去:
https://github.com/shiweifu/strutil/blob/master/escape.go
上面咱们来看如何调用这个新的办法。
第一种形式:
- fork strutil 库,关上 go.mod 文件,将第一行中的 module name 批改为一个新的 name
- 减少所须要的办法
- 减少新的 git tag
- 在你以后我的项目中,援用你批改后的这个 repo,替换地址以及版本号
这种形式相当于援用了一个新的库,与之前那个库曾经没有什么关系了。大多数时候,因为对代码批改过多,咱们并不会想要这么用。go mod 当然也思考到了这一点,go mod 提供了 go mod replace 办法来应答这种场景。
第二种形式:
- fork strutil 库
- 减少所须要的办法
- 在以后我的项目中,执行
go mod edit -replace
命令:
go mod edit -replace [old git package]@[version]=[new git package]@[version]
执行完命令后,咱们关上 go.mod
文件,发现最上面多了一条指令:
replace github.com/ozgio/strutil v0.3.0 => github.com/shiweifu/strutil v0.3.0
go mod replace 指令反对指定版本号,能够为 git tag,也能够为 git commit 日期 + git commit hash 的组合。
能够通过以下指令,来获取某个分支的最新版本:
go get github.com/shiweifu/strutil@master
此时会输入 master
分支的最新 commit 记录:
github.com/shiweifu/strutil@v0.3.1-0.20210615145512-3bd39e22cb0d
把这段版本号复制到 go.mod
文件 replace
指令,将对应的版本号替换成这个,而后再次执行,就能够应用咱们本人 fork 的 strutil 了:
package main
import (
"fmt"
"github.com/ozgio/strutil"
)
func main() {out := strutil.EscapeHTMLTag("<script>abc</script>")
fmt.Println(out)
}
咱们援用的还是 github.com/ozgio/strutil
这个库,而 EscapeHTMLTag
是咱们新增加的办法,这种形式只是对 go.mod
进行了批改,而后咱们能够对 ozgio/strutil
提一个 pr,如果咱们的代码被合并进仓库,咱们能够把 replace
语句给删除掉,这种形式没有毁坏原有的代码。