选择正确的Go Module Path

最近我在查看项目代码时,注意到有人在go.mod文件中将module path写为com.example.foo了。根据这个写法,相信屏幕前的读者也可以推断出这位开发人员可能是从Java阵营转到Go的。实际开发中可能有很多开发者会使用类似的内容作为module path,但这显然不是Go的推荐写法或惯用法。

在这篇简短的文章中,我就来介绍一下module path对Go源码构建、包导入路径以及开发协作的影响,以及符合惯例的module path应该是什么样子的。

我们先来复习一下什么是Go module path。

1. 什么是module path

在Go语言中,module path(模块路径)是指在Go开发中用来标识和定位模块的唯一字符串,用于指定在远程仓库或本地文件系统中存储模块代码的位置。

module path在go.mod文件中定义,比如下面这个示例:

// go.mod
module github.com/user/modulego 1.21.1

我们看到:一个典型的模块路径是一个URL格式字符串,可能是类似于github.com/user/module的形式,其中github.com/user/module就是module path。

在Go语言中,模块(module)是一种组织和管理代码的方式,也是Go代码版本管理的基本单元,我们可以在模块路径中包含主版本信息,比如:

// go.mod
module github.com/user/module/v2go 1.21.1

这表明该模块为v2版本,与前面的github.com/user/module是不向后兼容的两个模块。模块的使用者可以同时导入这两个不兼容的模块下的包,比如:

import ("github.com/user/module/foo"foov2 "github.com/user/module/v2/foo"
)

那么module path的选取和使用,对Go开发有何影响呢?我们继续向下看。

2. module path的影响

2.1 指示Go module网络位置

前面提到过,在Go语言中,我们通常使用模块的存储库地址作为模块路径的基础。这样做的好处是,Go编译器可以直接通过模块路径确定模块在网络上的位置,并从指定的位置下载需要的代码。这使得在使用第三方模块时非常方便,开发者只需要指定模块的路径,Go工具链就能够自动处理依赖关系,下载并编译所需的模块代码。

例如,如果一个模块的路径是github.com/user/module,那么Go工具链(尤其是Go编译器)就会认为该模块的代码存储在GitHub上的user用户下的module仓库中。当Go工具链需要引入该模块时,它会根据这个路径通过goproxy或直接去GitHub上下载相应的代码。

这种基于存储库地址的模块路径设计简化了模块的管理和依赖关系的处理,使得在Go项目中使用第三方模块变得更加方便和可靠。

2.2 对Go包路径的影响

Go module下的包的导入路径为module path+到包所在目录的相对路径,以module path为github.com/user/module的module下的pkg/foo目录下的包为例,foo包的导入路径为github.com/user/module/pkg/foo。

而如果像本文开头那样,使用com.example.foo作为module path,那么foo包的导入路径就变为了com.example.foo/pkg/foo,这显然难以理解,同时,com.example.foo这样的Java模式的字符串也无法指示go module的网络位置。

2.3 对编译的影响

module path对编译的影响体现在两方面:

首先,Go编译时通过module path来查找依赖的模块。如果Go module path不正确或不完整,那么编译可能会失败。非idiomatic的Go module path可能导致编译错误或难以诊断的问题。

其次,module path会影响采用go build默认构建出的二进制文件的名字,比如如果一个module path为github.com/user/mymodule,那么在该module下执行go build(不使用-o命令行标志),默认得到的二进制文件名为mymodule。

但如果module path为com.example.foo,那么得到的二进制文件名就为com.example.foo,这显然不是我们想要的。

2.4 对开发者协作的影响

Go模块路径的命名对开发者之间的协作也有着重要的影响,主要体现在两方面:

  • 唯一性和命名空间

模块路径应当保持唯一,以避免与其他模块产生冲突。通常情况下,使用域名作为模块路径的一部分可以确保全球唯一性。在团队内部,也可以基于公司或组织的名称来命名模块路径,以确保模块的唯一性。

  • 依赖管理

使用清晰、有意义、可以指示位置和版本的模块路径可以帮助开发者更好地管理依赖关系。当其他开发者在引入你的模块时,他们可以通过模块路径来确定正确的依赖版本,以及如何与你的模块进行集成。

3. 如何选择一个好的module path

通过上面的秒数,其实我们已经可以勾勒出一个好的module path的画像了。当然这也是Go社区的最佳实践。

通常情况下,module path应该基于模块的存储库地址,并使用简短、易于理解的路径。

就像前面提到的那样,如果你的module存储在GitHub上并可公开,那么module path一般是github.com/user/module。

如果你的module公司内部,不能公开的,那么可以使用一个私有的存储库地址,例如:company.com/dept/go/module。

无论公开的,还是私有的,你都可以定制module path,这方面的方案可以参考我之前编写的有关定制Go module的拉取方案[1]

如果是仅在本地使用的日常练习项目,那么Go module path的使用可以宽松一些,可以无需在乎其对go module网络位置、开发者协作的影响,可使用像demo这样的单个词的module path,仅注意下其对包路径和编译结果的影响即可。

4. 小结

综上,我们看到:Go module path对Go module网络位置、包路径、编译和开发者协作都有重要影响。遵循Go社区的最佳实践,选择一个好的Go module path可以提高代码可读性和可维护性,并简化多人协作,帮助Go开发者更好地使用Go模块系统。


Gopher部落知识星球[2]在2024年将继续致力于打造一个高品质的Go语言学习和交流平台。我们将继续提供优质的Go技术文章首发和阅读体验。同时,我们也会加强代码质量和最佳实践的分享,包括如何编写简洁、可读、可测试的Go代码。此外,我们还会加强星友之间的交流和互动。欢迎大家踊跃提问,分享心得,讨论技术。我会在第一时间进行解答和交流。我衷心希望Gopher部落可以成为大家学习、进步、交流的港湾。让我相聚在Gopher部落,享受coding的快乐! 欢迎大家踊跃加入!

d1ab01aa466e6182ab28c7699514c79e.jpeg02dddac3150bc97b2bd5a2655d8ea2de.png

8305b1ab585fadf69f4cc1d7f260087f.pngc1276f5e20ac3fc4eb2c8817a3b39b50.jpeg

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址[3]:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻) - https://gopherdaily.tonybai.com

我的联系方式:

  • 微博(暂不可用):https://weibo.com/bigwhite20xx

  • 微博2:https://weibo.com/u/6484441286

  • 博客:tonybai.com

  • github: https://github.com/bigwhite

  • Gopher Daily - https://gopherdaily.tonybai.com

3ff1d77e746bfb4779ba509a4f0c58fb.jpeg

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

参考资料

[1] 

定制Go module的拉取方案: https://tonybai.com/2021/09/03/the-approach-to-go-get-private-go-module-in-house

[2] 

Gopher部落知识星球: https://public.zsxq.com/groups/51284458844544

[3] 

链接地址: https://m.do.co/c/bff6eed92687

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/810730.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis和Mysql如何保证数据一致性?

一份数据同时保存在数据库和Redis中,当数据发生变化时需要同时去更新Mysql和Redis,由于这个更新有先后顺序并且它不像Mysql里面的多表事物一样可以满足ACID的事物特性,所以就会出现数据一致性的问题。 对于这种情况解决方案主要有以下几种&a…

Jmeter针对多种响应断言的判断

有时候response返回的结果并非一种,有多种,需要对这几种进行判断的时候需要使用Bean Shell。 (1)首先获取响应数据 String response prev.getResponseDataAsString(); ResponseCode 响应状态码 responseHeaders 响应头信息 res…

Peter算法小课堂—动态规划斜率优化

大家来到这一堂课,就说明大家已经学过函数了 直线方程:ykxb 大家可以算一算。 其实,在数学上,这玩意要分类讨论 那么,这唯一的交点就是我们要背出来的 直线最值 这像一个分段函数 其实,只有部分直线能提供…

支付牌照7000万出让:成都摩宝以1.29亿挂牌价出让60.33% 股份

重庆中渝兴拍科技有限公司受重庆力帆控股有限公司委托于2024年04月26日10时至2024年04月27日10时止在淘宝网阿里资产交易平台对力帆持有成都摩宝网络科技有限公司60.332806%股权转让进行公开拍卖活动,起始价为129,000,000元。 相关情况如下: 成都摩宝网…

docker-compose yaml指定具体容器网桥ip网段subnet

docker-compose 启动yaml有时可能的容器网段与宿主机的ip冲突导致宿主机上不了网,这时候可以更改yaml指定subnet 宿主机内网一般是192**,这时候容器可以指定172* version: 3.9 services:coredns:image: coredns/coredns:1.10.0container_name: coredns…

详解Qt添加外部库

在Qt项目中添加外部库是一项常见任务,无论是静态库还是动态库都需要正确的配置才能让项目顺利编译链接。以下是详细步骤和不同场景下的配置方法: 方法一:手动编辑.pro文件 添加头文件路径: 在Qt项目中的.pro文件中使用INCLUDEPAT…

IO_DAY7

1:实现2个终端之间的互相聊天 要求:千万不要做出来2个终端之间的消息发送是读一写的&#xff0c;一定要能够做到&#xff0c;一个终端发送n条消息&#xff0c;另一个终端一条消息都不回复都是没有问题的 终端A&#xff1a; #include<myhead.h> int main(int argc, char…

【YOLOv9改进[损失函数]】使用结合InnerIoU和Focaler的各种损失函数助力YOLOv9更优秀

目录 一 回归损失函数&#xff08;Bounding Box Regression Loss&#xff09; 1 Inner-IoU 2 Focaler-IoU&#xff1a;更聚焦的IoU损失 二 改进YOLOv9的损失函数 1 总体修改 ① utils/metrics.py文件 ② utils/loss_tal_dual.py文件 2 各种机制的使用 ① 使用结合Inn…

ActiveMQ 02 常用API

Active MQ 02 常用API 事务 session.commit(); session.rollback();用来提交/回滚事务 Purge 清理消息 签收模式 签收代表接收端的session已收到消息的一次确认&#xff0c;反馈给broker ActiveMQ支持自动签收与手动签收 Session.AUTO_ACKNOWLEDGE 当客户端从receive…

【01背包】滚动数组优化实现一维01背包DP(对比朴素写法)

01背包 代码 背包问题的滚动数组优化版本建议在完全弄懂了普通的二维01背包问题后再进行食用&#xff0c;不然会出现消化不良的症状… 我们可以将背包问题中DP数组的下标看作成两个集合 下面对比两种不同实现方法的区别&#xff1a; 朴素二维DP版本 使用dp[不超过i的物品集合]…

全量知识系统 程序详细设计 之 三种“活物” 之1(QA百度文库 )

Q1. 今天聊聊 全知系统中 三种“活物”。先从他们的一个简单描述开始&#xff1a;自主&#xff1a;计算机“集群”的“沉”与“浮”自然&#xff1a;AI “众生”的“世”和“界”自由&#xff1a;人类 “公民”的“宇”或“宙” 这是一个非常有趣且深刻的主题&#xff0c;将全…

2024年MCN商业模式运营体系行业发展分析

【干货资料持续更新&#xff0c;以防走丢】 2024年MCN商业模式运营体系行业发展分析 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 mcn运营资料包&#xff08;完整资料包含以下内容&#xff09; 目录 MCN机构运营方案的概要&#xff1a; 一、MCN机构定位与目…

关于java分页功能以及传参规范

不用插件 //当前页码private static final Integer currentPage 2;//设置每页个数private static final Integer pageSize 5;Testpublic void test8() {//手写一个分页测试&#xff0c;不用插件List<Integer> list new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7…

Docker 国内镜像

Docker 国内镜像 安装好Docker/Docker Desktop后&#xff0c;其registry server是默认指向https://hub.docker.com的。在国内该hub源访问速度异常慢&#xff0c;可以通过切换至国内镜像仓库来解决这一问题。 sudo vi /etc/docker/daemon.json 添加以下内容&#xff1a; { “re…

GPT建模与预测实战

代码链接见文末 效果图&#xff1a; 1.数据样本生成方法 训练配置参数&#xff1a; --epochs 40 --batch_size 8 --device 0 --train_path data/train.pkl 其中train.pkl是处理后的文件 因此&#xff0c;我们首先需要执行preprocess.py进行预处理操作&#xff0c;配置参数…

Android-NDK的linux交叉编译环境

NDK工具包下载 NDK 下载 | Android NDK | Android Developers https://github.com/android/ndk/wiki/Unsupported-Downloads 以android-ndk-r26c下载为例&#xff0c;下载后将压缩包解压至/usr目录下 CMakeLists编译选项设置 编译平台变量判断条件中增加一下android条件…

【HDFS】DirectoryScanner与append操作对副本状态判定是否存在冲突?

结论: 不存在问题。 DirectoryScanner周期性地运行,扫描整个DN磁盘上的块与内存里的块做比较。 删除那些内存里没有的但是在磁盘上存在的块, 处理重复块等等。 最近在更细粒度化DN锁。在看到ReplicaMap#replicas方法时,阅读相关代码。 发现DirectoryScanner#scan 与appen…

ubuntu下man手册 查不到 pthread_mutex_lock等系列函数用法的问题

问题 在ubuntu系统中无法man到 pthread_mutex_lock pthread_mutex_trylock pthread_mutex_unlock等函数 $ man pthread_mutex_lock 没有 pthread_mutex_lock 的手册页条目解决方式 输入以下命令 sudo apt-get install manpages-posix manpages-posix-dev 然后输入密码 再次m…

Hive和Pig有什么区别吗?

尽管Hive和Pig都是用于处理大数据的Hadoop生态系统的工具&#xff0c;但它们之间的主要目标和使用方法有很大的差异。以下是对两者的一些比较&#xff1a; 数据处理&#xff1a;Hive更像是一个用于进行数据分析的工具。它提供了一种名为HQL的查询语言&#xff0c;语法类似于SQL…

MobaXterm无法登陆oracle cloud的问题

问题 我在oracle cloud上创建实例的时候&#xff0c;只能使用密钥的方式登陆&#xff0c;当时下载了私钥文件。实例创建好以后&#xff0c;在mobaxterm上使用这个私钥文件无法登陆 排查 尝试使用mobaxterm的keygen&#xff0c;把私钥文件转成ppk格式&#xff0c;还是不行。…