用c.char接const char报conflicting types,因cgo不保留const修饰符;唯一可靠解法是在cgo注释中typedef const char为别名(如c_char_t),go端用c.c_char_t声明回调参数,并在函数内用(c.char)(unsafe.pointer(msg))转为*c.char供c.gostring使用。

为什么用 *C.char 接 const char* 会报 conflicting types?
因为 CGO 不保留 const 修饰符——*C.char 永远映射为 char*,而 C 编译器把 char* 和 const char* 当作两个不兼容类型。哪怕你只读不写,只要函数签名里写了 const,C 侧声明和 CGO 自动生成的导出函数签名就必须严格一致,否则链接前就卡在编译阶段。
典型错误信息是:error: conflicting types for 'myCallback',后面跟着两行声明对比,一眼就能看出左边是 const char*、右边是 char*。
- 这不是 Go 写法错,也不是 C 头文件错,是 CGO 类型桥接层的硬性限制
- 加
// #include <string.h></string.h>或改CFLAGS完全无效 -
unsafe.Pointer强转或手动 cast 在导出函数签名里不被允许,编译直接拒
怎么让 Go 导出函数真正匹配 const char*?
唯一可靠方式:在 CGO 注释块里用 typedef 定义带 const 的别名类型,让 CGO 把它当独立类型处理。
正确写法示例:
/* typedef const char c_char_t; typedef void (*log_cb)(c_char_t*, int); void register_logger(log_cb cb); */ import "C"
对应 Go 端必须用 *C.c_char_t,不是 *C.char:
//export myLog
func myLog(msg *C.c_char_t, level C.int) {
s := C.GoString((*C.char)(unsafe.Pointer(msg)))
fmt.Printf("[C] %s (level %d)\n", s, int(level))
}
-
C.c_char_t是 CGO 自动识别的类型别名,生成的 C 函数签名带const - 转换时仍需
(*C.char)(unsafe.Pointer(msg)),因为C.GoString只接受*C.char - 别名名不能用下划线开头(如
_cchar),CGO 不识别;推荐用c_char_t或cstr_t
结构体里的函数指针回调怎么赋值?
Go 把 C 结构体中 void (*)() 类型字段映射成不可赋值的 *[0]byte,直接写 s.cb = C.myFunc 会报 cannot use ... as type *[0]byte。
必须靠 C 辅助函数中转:
/*
typedef struct { void (*on_data)(const char*); } handler_t;
extern void go_on_data(const char*);
static void set_on_data(handler_t* h) { h->on_data = go_on_data; }
*/
import "C"
然后在 Go 中调用:
var h C.handler_t C.set_on_data(&h)
-
extern void go_on_data(...)必须显式声明,否则 C 编译器找不到符号 - 不要用
static inline或宏封装 setter,链接时可能丢符号 - 若结构体有多个回调,每个都配一个 setter 更安全;泛化 setter 需额外 void* 参数,易出错
回调里访问字符串要注意什么?
const char* 只保证 C 侧不修改内存,但不保证生命周期——C 传来的指针可能指向栈上临时数据、静态缓冲区或已释放内存。
- 立刻用
C.GoString或C.GoStringN拷贝内容,别存指针 - 如果 C 侧传的是不定长字符串(比如没 null-terminated),必须配合长度参数用
C.GoStringN - 不要在回调里调用
C.free或其他 C 内存管理函数,除非你 100% 确认该内存由你分配且 C 不再使用 - 多线程环境下,C 回调可能并发进入 Go 函数,注意共享变量加锁
最常被忽略的是:C 传来的 const char* 可能只在回调函数执行期间有效,一返回就失效。拷贝这一步不能省,也不能延迟。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











