“cannot open shared object file”是运行时错误,表明启用了CGO且依赖系统动态库(如libpq.so.5),但目标机器未安装对应so或版本不匹配;go build默认静态链接,仅当CGO_ENABLED=1且显式配置外部链接时才生成动态可执行文件。

编译时提示“cannot open shared object file”
这不是 Go 编译失败,而是运行时报的错——说明你启用了 CGO 且依赖了系统动态库(如 libpq.so.5、libcrypt.so.1),但目标机器没装对应 so 文件,或版本不匹配。
- 先确认是否真需要动态链接:
go build默认是静态链接,只要没设CGO_ENABLED=1,就不会找任何 .so - 如果必须用 cgo(比如连 PostgreSQL),则目标机器必须预装对应库:
ldd ./myapp要能列出libpq.so.5 => /usr/lib/x86_64-linux-gnu/libpq.so.5这类有效路径 -
LD_LIBRARY_PATH是临时方案,上线应改用-Wl,-rpath,/usr/local/lib写死路径(Linux)或-Wl,-rpath,@loader_path(macOS) - 交叉编译时绝对不要开
CGO_ENABLED=1:x86_64 主机上编译 ARM64 的libpq.so链接必然失败,工具链 ABI 不兼容
ldd 显示 “not a dynamic executable” 却以为链接参数漏了
这是最典型的误解。ldd 报这个,恰恰说明你没启用动态链接——Go 默认根本不生成动态可执行文件。
- 只有显式加了
-ldflags="-linkmode=external"并设CGO_ENABLED=1,才可能生成动态链接产物 -
-ldflags '-extldflags "-shared"'是给buildmode=c-shared用的,不是给普通go build加的;加了反而报错 - 想验证是否真动态:运行
file ./myapp,输出含dynamic linked才算成功;若写statically linked,那ldd就必然报 not a dynamic executable
plugin.Open 报 “built with a different version of package”
这不是路径或版本号问题,是 Go 编译指纹不一致。replace 只改源码位置,不改构建哈希。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 主程序和插件必须用同一命令构建:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -buildmode=plugin -o plugin.so plugin.go - 两边
go.mod的require必须完全一致,go list -m all输出要逐行相同 -
plugin在 Windows 上根本不可用,Linux/macOS 也要求 Go 小版本(如 1.22.2 vs 1.22.3)严格一致 - 插件里不能有
cgo代码,否则CGO_ENABLED=0下直接编译失败
想让 Python/C 调用 Go 函数,却误用 plugin.Open
plugin.Open 是 Go 内部机制,只认 Go 插件;外部语言调用必须走 C ABI,也就是 buildmode=c-shared。
立即学习“go语言免费学习笔记(深入)”;
- 导出函数前必须写
//export Add(注意//和export之间**不能有空格**) - 必须在
package main里,且包含空的func main() {} - 参数/返回值只能是 C 类型:
C.int、*C.char,不能是string或[]byte - Windows 下生成
.dll和.h,Linux 下生成.so和.h,但头文件内容一致,C 端可直接 include
go build 命令,而是搞清你到底要“Go 加载别人”,还是“别人加载 Go”——前者靠 cgo 声明 + LDFLAGS,后者靠 buildmode=c-shared + C 兼容签名,两者不能混。

















