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 时尝试下一个来源,不表示任何失败都一定回退;这个区别在排查网络问题时很重要,见模块下载规则。

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,提交前跑测试;只引入用得到的依赖。一个新的依赖不只是少写几行代码,还意味着版本更新和维护工作。
原来的编码规范截图保留作记录,实际规则优先看官方说明和当前项目约定。


