不能。go 默认不生成传统动态库,但可通过-buildmode=c-shared生成c abi兼容的.so或.dll供外部调用,需满足main包、//export注释、c兼容类型等硬性条件。

Go 能否直接生成 .so 或 .dll?
不能。Go 默认编译出的是静态链接的可执行文件或归档(.a),不生成传统意义上的动态链接库(.so / .dll)。但 Go 支持 buildmode=c-shared,能导出 C 兼容的符号,生成带封装层的 .so(Linux/macOS)或 .dll(Windows),供 C/C++/Python 等调用——这本质是「C ABI 兼容的共享库」,不是 Go 原生动态模块。
使用 buildmode=c-shared 的硬性前提
必须满足以下全部条件,否则编译失败或运行时崩溃:
-
main包必须存在,且入口函数为main()(哪怕空实现) - 所有导出函数必须以大写字母开头,并用
//export FuncName注释标记 - 函数签名只能含 C 兼容类型:如
*C.char、C.int、C.size_t,不能出现string、slice、struct(除非手动转成 C 内存布局) - 不能调用 Go 运行时依赖线程本地存储的功能(如
net/http、time.Sleep),否则在多线程 C 环境中可能死锁或 panic
Linux/macOS 下生成 .so 的典型流程
假设有一个 lib.go:
package main
<p>/*</p><h1>include <stdlib.h></stdlib.h>
</h1><p>*/
import "C"
import "unsafe"</p><p>//export Add
func Add(a, b C.int) C.int {
return a + b
}</p><p>//export GoString
func GoString(s <em>C.char) </em>C.char {
goStr := C.GoString(s)
return C.CString("hello, " + goStr)
}</p><p>func main() {} // 必须有,但可为空
</p>
执行:
GOOS=linux GOARCH=amd64 go build -buildmode=c-shared -o libmath.so lib.go
会输出 libmath.so 和 libmath.h。注意:.h 是自动生成的头文件,声明了导出函数原型,C 端必须包含它;.so 本身依赖 libc 和 Go 运行时(libgo.so 不打包进去),所以部署时需确保目标系统有对应 Go 版本的运行时,或改用 -ldflags="-linkmode external -extldflags '-static'"(效果有限,不推荐)。
Windows 下生成 .dll 的关键差异
命令类似,但行为更敏感:
- 必须用
GOOS=windows GOARCH=amd64 go build -buildmode=c-shared -o libmath.dll lib.go - 生成的
.dll依赖libgcc和libwinpthread(MinGW 工具链),若目标机器无 MinGW 运行时,会报错The code execution cannot proceed because libwinpthread-1.dll was not found - 导出函数在 Windows 上默认不带
__declspec(dllexport),但c-shared模式已自动处理,无需手动加 - Go 1.21+ 在 Windows 上对
c-shared的栈分裂支持仍有问题,避免在导出函数中触发 goroutine 创建(比如调用http.Get)
跨平台发布时,别指望一个 .so 文件能在 Windows 上加载,也别指望 .dll 能被 Linux dlopen —— ABI 和加载器完全不同,这是操作系统层面的隔离,不是 Go 能绕过的。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











