Go语言不支持相对路径导入(如"./utils"),因其工具链硬性限制;必须使用基于模块的绝对路径,如"github.com/you/project/utils",并确保go.mod模块名含域名、子包package声明与目录名一致、项目不在GOPATH/src下。

Go 语言根本不支持 import "./utils" 这类相对路径导入,这不是配置问题,而是工具链硬性限制——go build、go test 等命令会直接拒绝解析以 ./ 或 ../ 开头的导入路径。唯一可行的路径是基于模块(module)的绝对导入路径。
为什么 import "./xxx" 一定失败
Go 的 import 解析机制从不以当前文件为基准,它只认两种根:$GOPATH/src/(旧模式)或模块根目录下的 go.mod 所声明的 module 名。无论你把 main.go 放在哪,import "./utils" 都不会被识别为合法包路径。
-
go run main.go单文件运行时看似“能用”,是因为 Go 临时推导了路径,但该行为不参与模块构建,也不生成可复现的依赖图,生产环境完全不可靠 - IDE(如 VS Code + gopls)报错“cannot find package”或标红,往往就是检测到了非法相对路径,不是插件问题,而是提前拦截了错误
- 即使代码侥幸通过
go run,一旦执行go build、go test或集成 CI,必然失败
正确做法:用模块路径替代相对路径
核心逻辑是:所有本地子包都必须通过 module 名 + 目录相对位置 构成完整导入路径。例如模块名是 github.com/you/project,utils/ 在项目根下,则导入必须写成 import "github.com/you/project/utils"。
- 先确保项目根目录已执行
go mod init github.com/you/project(模块名建议含域名,避免冲突) -
utils/目录下每个.go文件开头必须有package utils声明(包名不必和目录名完全一致,但强烈建议一致) - 在
main.go中导入时,路径必须从模块名开始,不能省略,例如import "github.com/you/project/utils",而不是import "utils"或import "./utils" - 如果子包在嵌套目录(如
internal/db/),导入路径就是"github.com/you/project/internal/db",与文件系统深度严格对应
跨目录引用另一个本地模块(非子包)
当两个模块物理上分离(比如 app/ 和 shared/ 各自带 go.mod),又想让 app 引用本地 shared,就得用 replace 指令,而不是改导入路径。
立即学习“go语言免费学习笔记(深入)”;
- 在
app/go.mod末尾添加:replace github.com/you/shared => ../shared(路径基于app/go.mod位置计算) -
app/main.go中仍写import "github.com/you/shared",不能写成import "../shared"或其他变体 - 执行
go mod tidy后,检查输出是否包含=> ../shared,否则说明路径不对或shared/go.mod中的module名不匹配 -
replace只影响构建,不改变源码中的导入路径;发布前需删掉replace行,并发布真实版本
容易忽略的三个关键点
很多人按步骤做了还是报错,往往卡在这三处:
-
go.mod文件存在,但模块名写成了module myproject(无域名),导致导入路径"myproject/utils"被 Go 认定为“标准库或未知远程包”,必须用类似module github.com/you/myproject的格式 - 子包目录下
.go文件的package声明与目录名不一致,比如目录叫router,但文件里写package http,则外部无法通过"github.com/you/project/router"导入(包名是http,不是router) - 项目目录仍在
$GOPATH/src/下,且未启用 modules(GO111MODULE=off),此时 Go 会回退到 GOPATH 模式,忽略go.mod,必须移出$GOPATH或显式设置GO111MODULE=on


















