作者回复: 非常好的问题。go module机制在您提到的工作场景下目前的体验做的还不够好。在Go 1.17版本及之前版本的解决方法是使用go mod的replace指示符(directive)。假如你的module a要import的module b将发布到github.com/user/repo中,那么你可以手动在module的go.mod中的require块中手工加上一条: require github.com/user/repo v1.0.0 注意v1.0.0这个版本号是一个临时的版本号。 然后在module a的go.mod中使用replace将上面对module b的require替换为本地的module b: replace github.com/user/repo v1.0.0 => module b本地路径 这样go命令就会使用你本地正在开发、尚未提交github的module b了。 你可以试试。
作者回复: 你的理解非常正确,给你点个赞!
作者回复: go默认是开启CGO_ENABLED的,即CGO_ENABLED=1。但编译出来的二进制程序究竟有无动态链接,取决于你的程序使用了什么包。如果就是一个hello,world,那么你编译出来的将是一个纯静态程序。 如果你依赖了网络包或一些系统包,比如用http包编写了一个web server(见第9讲示例),那么你编译出来的二进制程序又会是一个包含动态链接的程序。 原因就在于目前的go标准库中,某些功能具有两份实现,一份是c语言实现的,一份是go语言实现的。在cgo_enable开启的情况下,go链接器会链接c语言的版本,于是就有了依赖动态链接库的情况。如果你将cgo_enabled置为0,你再重新编译链接,那么go链接器会使用go版本的实现,这样你将得到一个没有动态链接的纯静态二进制程序。
作者回复: 嗯,国内的几大goproxy服务都是可以的。
作者回复: 1. 使用github.com/...作为module path是因为多数实用级module多是上传到github上的。用这种示例便于后续与真实生产接驳。但对于本地开发使用的简单示例程序而言,你说的没错。module path可以任意起,比如: module demo1 也是ok的。 第二个问题,go mod tidy下载的第三方包一般在$GOPATH/pkg/mod下面。如果没有设置GOPATH环境变量,其默认值为你的home路径下的go文件夹。这样第三方包就在go文件夹的pkg/mod下面。
作者回复: 作为一个多年gopher的心底话,现在go开发已经完全离不开gofmt或类似工具了。并且这些标准风格格式化工具与各种编辑器或IDE结合后,是在“quiet模式”下帮助开发者,并不需要开发者付出额外的工作量。
作者回复: 问题1:go module与gopath的一个重要区别就是可以将项目放在任意路径下,而无需局限在$GOPATH/src下面。我之所以将一个module放在一个任意路径下,就是故意要与GOPATH模式区分开的。 问题2:有些时候,无论怎么翻译都不能很理想的呈现英文作者的原意,因此向go mod tidy我倾向于直接使用原文,而不要翻译为中文。 关于你的建议,我后续会重点考虑的,感谢。
作者回复: 1-1. go mod init后面的路径就是go.mod中module后面的路径,代表的是module path。 1-2. go mod init命令的实际行为就是在当前目录下创建一个go.mod,而这个go.mod将当前目录转换为一个go module。 1-3. go module是一个逻辑概念。文中也说了,它更像一个命名空间的概念。它与文件夹名称无关。有了go.mod后,这个文件夹下的各个包就算是这个go module下面的包了。包的导入路径也是以module path为前缀的。 2. 确认一下你本地的go编译器版本?确认go module构建模式已开启。确认一下是否在go.mod所在目录执行的go mod tidy?
作者回复: 如果从编译的角度来讲,go包是编译的基本单位,每个go包编译为一个.a文件,每个java public class编译为一个class文件。它们的确有些类似。但从内容结构上来说,go包是一个命名空间的概念,可以包含go所有语法元素。java class就是一个拥有多个属性+方法的抽象。
作者回复: 👍