← 返回文章列表

golang学习记录(12)

区分 package 与 module,整理 go.mod、go.sum、依赖命令、GOPROXY 和 replace 的正确用法。

1、package 和 module 先分开

package 是组织 Go 源码的单位;module 则是一组由 go.mod 管理的包。一个 module 可以有很多个 package,不是每个目录都要放一个 go.mod。可以对照官方的模块组织示例看目录和导入路径的关系。

同一目录中的普通 Go 文件通常属于同一个包,可以直接使用包内名字。外部测试可以用 xxx_test 包,这是常见的例外。main 包的 main() 是可执行程序入口。

比如最简单的项目:

hello/
├── go.mod
├── main.go
└── greeting/
    └── greeting.go

在 hello 目录执行:

go mod init example.com/hello

greeting/greeting.go:

package greeting

func Message() string {
	return "hello, Go"
}

main.go:

package main

import (
	"example.com/hello/greeting"
	"fmt"
)

func main() {
	fmt.Println(greeting.Message())
}

在项目根目录执行 go run .,输出 hello, Go。导入路径由 module 路径和子目录组成,不是简单写一个本地磁盘路径。

2、import 的几种方式

普通导入以后,用包名访问导出的名字。需要避开重名时,可以加别名:

import myjson "encoding/json"

还有两种写法:import _ "包路径" 用于仅执行初始化等副作用;import . "包路径" 会把导出名字放进当前文件作用域。后一种容易让名字来源变得不清楚,普通业务代码通常不需要它。

完整规则可以对照 Go 语言规范中的包与导入。

3、go.mod 和 go.sum

go.mod 记录 module 路径、Go 版本要求和依赖等信息。go.sum 保存下载模块内容的校验记录,它不是传统意义上覆盖全部依赖选择逻辑的锁文件。

这两个文件通常都应提交。具体依赖如何选择以及各个指令的意义,以 Go Modules Reference为准。

原有模块记录

4、常用指令分别干什么?

按官方依赖管理说明,先区分修改依赖与安装工具。

指令用途
go mod init 模块路径创建模块
go mod tidy按代码和测试需要补充、清理依赖记录
go get 包路径@版本在当前模块中调整依赖版本
go mod download下载模块依赖
go list -m all查看当前模块依赖列表
go mod graph查看模块依赖关系
go mod verify检查本地模块缓存是否被改动
go install 工具路径@版本安装指定版本的可执行工具

现在安装 CLI 工具,通常使用 go install ...@版本,不要再把 go get 当成通用工具安装命令。模块有变化后,跑一遍 go mod tidy 和 go test ./...,并看一下 diff,确认没有无意升级一大批依赖。

5、GOPROXY

先查看当前值:

go env GOPROXY

需要时可以设置,例如:

go env -w GOPROXY=https://goproxy.cn,direct

它修改的是 Go 工具链的持久配置,不只作用于当前终端。选代理时也要考虑自己的网络环境和组织要求。

逗号分隔的代理列表通常在 404/410 时尝试下一个来源,不表示任何失败都一定回退;这个区别在排查网络问题时很重要,见模块下载规则。

原有 GOPROXY 设置记录

6、replace 的正确写法

replace 可以把某个模块替换为本地目录或另一个模块版本。它是 go.mod 中的指令;命令行编辑它,用的是 go mod edit -replace,没有 go mod replace 这个命令。

比如本地同时开发两个模块:

module example.com/hello

go 1.24

require example.com/common v0.0.0

replace example.com/common => ../common

也可以在项目目录运行:

go mod edit -replace=example.com/common=../common
go mod tidy

被替换的目录本身也应是一个模块。replace 不会凭空添加一个依赖;而且主模块里的本地替换不会自动替使用你这个库的人生效。发布前检查本地路径替换是否还应该保留。相关规则见 go.mod 的 replace 说明。

7、平时怎么保持项目干净?

源码使用 gofmt,提交前跑测试;只引入用得到的依赖。一个新的依赖不只是少写几行代码,还意味着版本更新和维护工作。

原来的编码规范截图保留作记录,实际规则优先看官方说明和当前项目约定。

编码规范旧记录 1

编码规范旧记录 2

编码规范旧记录 3

关于这篇文章的日期

保留旧站原始文章标注的日期;实际开始写作的时间可能更早。

同一系列 · Go 基础学习

上一篇golang学习记录(11) ←下一篇golang学习记录(13) →