网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
mkdir examples
cd examples
mkdir ModuleA
cd ModuleA
go mod init github.com/unitymarvel/ModuleA
touch A.go
cd …
**步骤2:创建ModuleB**
mkdir ModuleB
cd ModuleB
go mod init github.com/unitymarvel/ModuleB
touch B.go
cd …
**步骤3:创建Demo**
mkdir Demo
cd Demo
go mod init github.com/unitymarvel/Demo
touch Demo.go
cd …
经过上面3步,会在examples目录中创建三个子目录:ModuleA、ModuleB和Demo,并且每一个子目录中都有两个文件,一个是go文件,一个是go.mod文件,使用tree命令会看到examples目录中的完整结构,如下图所示:
![](https://img-blog.csdnimg.cn/d0101cf51530435482de8cb282ece059.png)
**步骤4:编写B.go的代码**
package ModuleB
func Greet(name string) string{
return "Hello " + name
}
**步骤5:编写A.go的代码**
package ModuleA
import (
“fmt”
“github.com/unitymarvel/ModuleB”
)
func OutputMsg(str string) {
fmt.Println(ModuleB.Greet(str))
}
**步骤6:编写Demo.go的代码**
package main
import (
“fmt”
“github.com/unitymarvel/ModuleA”
“github.com/unitymarvel/ModuleB”
)
func main() {
ModuleA.OutputMsg(“李宁”)
fmt.Println(ModuleB.Greet(“Bill”))
}
很明显,在A.go文件中引用了ModuleB模块,而在Demo.go文件中同时引用了ModuleA模块和ModuleB模块。在终端进入demo目录,并执行go run Demo.go,肯定不会执行的,会抛出如下的异常:
![](https://img-blog.csdnimg.cn/21354388bdfd4425abec058cea61532f.png) 错误信息的基本含义就是github.com/unitymarvel/ModuleA和github.com/unitymarvel/ModuleB这两个地址根本没有对应的模块,所以就要使用本地模块,但Go编译器也不知道本地模块在什么位置,所以就会运行失败。
现在要让Go编译器知道本地模块的位置,通常在go.mod文件中使用replace指令将域名映射到本地的模块目录,所以应该按下面的步骤修改对应模块的go.mod文件。
**步骤7:修改ModuleA/go.mod文件**
修改后的结果如下:
module github.com/unitymarvel/ModuleA
go 1.19
require github.com/unitymarvel/ModuleB v1.0.0
replace github.com/unitymarvel/ModuleB => …/ModuleB
replace执行中,”=>“左侧的部分是模块对应的网址,右侧对应了本地模块目录,可以使用相对路径,也可以使用绝对路径。
**步骤8:修改Demo/go.mod文件**
修改后的结果如下:
module github.com/unitymarvel/Demo
go 1.19
require github.com/unitymarvel/ModuleA v1.0.0
require github.com/unitymarvel/ModuleB v1.0.0
replace github.com/unitymarvel/ModuleA => …/ModuleA
replace github.com/unitymarvel/ModuleB => …/ModuleB
现在运行go run Demo.go,就会输出如下的内容:
Hello 李宁
Hello Bill
以上使用了go modules的方式管理了ModuleA和ModuleB,尽管go.mod文件中使用了相对路径,pull也不会有路径问题,但由于ModuleB被引用了两次,这就意味着,如果ModuleB的位置或模块名发生了变化,那么就要修改两个地方,如果一个模块被引用了100次,那么就要修改100个地方,这将会带来灾难性的后果,有可能整个工程最后会乱套了。而如果使用go.work文件管理模块,那么不管模块路径和模块名如何变化,只需要修改go.work文件中的内容即可,而且不管模块名被引用多少次,只需要修改一次即可。
### 2. 使用工作区管理Go模块
使用工作区管理Go模块必须使用Go1.18或以上版本,使用其他Go版本的同学赶快升级。
在终端进入工程根目录,执行下面的命令创建go.work文件。
go work init ModuleA ModuleB Demo
其中ModuleA、ModuleB和Demo是3个模块的相对路径,如果读者使用了其他路径,需要将其修改成本机的模块路径。执行完命令后,会在工程根目录生成一个go.work文件,内容如下:
go 1.19
use (
./Demo
./ModuleA
./ModuleB
)
其中use指令用于指定模块的路径(相对路径或绝对路径)。现在可以将Demo模块和ModuleA模块的go.mod文件中的replace指令和require指令全部删除了,接下来在Demo目录下执行go run Demo.go文件,就会执行成功,并输出如下内容:
Hello 李宁
Hello Bill
如果想关闭工作区模式,可以使用workfile命令行参数,如下所示:
go run -workfile=off Demo.go
go build -workfile=off Demo
### 3. 设置全局模块名
可能细心的读者会发现一个问题,使用go.work的use指令,模块路径问题是解决了,但还有一个问题没解决,那就是模块名问题,如果修改模块名(如改变了模块名的网址),仍然需要修改大量的源代码。为了解决这个问题,可以在go.work文件中使用replace指令为模块名起一个别名,例如,可以将go.work文件改成如下的内容:
go 1.19
use (
./Demo
./ModuleA
)
replace MA v1.2.3 => ./ModuleA
replace MB v1.2.3 => ./ModuleB
其中MA是MobileA的别名,MB是MobuleB的别名,目前这两个别名都指向本地模块,在引用MobuleA和MobuleB时,就可以直接使用MA和MB了,代码如下:
Demo.go文件的代码:
package main
import (
“fmt”
“MA”
“MB”
)
func main() {
ModuleA.OutputMsg(“李宁”)
fmt.Println(ModuleB.Greet(“Bill”))
}
![img](https://img-blog.csdnimg.cn/img_convert/6f3e1fd441443df1572f6c9ca41baccf.png)
![img](https://img-blog.csdnimg.cn/img_convert/27d8e023fdc686acbc7efa3d8bd3af6f.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618658159)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618658159)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**