You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CGO中从C Union读取char*字符串?

从C联合体的value_struct中读取char*字符串到Go的正确方法

我有一个用于存储数据的C联合体,定义如下:

union data_union {
  char *string_val;
  int8_t int8_val;
  int64_t int64_val;
  // 其他类型
};

typedef enum {
  MY_STRING,
  MY_INT8,
  MY_INT64,
  // 其他类型
} data_type;

struct value_struct {
  data_type type;
  data_union data;
};

目前我可以通过以下方式从C的value_struct中读取int8值到Go:

int8_val := *(*C.int8_t)(unsafe.Pointer(&(cValue.data[0])))
goInt := int64(int8_val)

读取int64值的方式类似:

int64_val := *(*C.int64_t)(unsafe.Pointer(&(cValue.data[0])))
goInt := int64(int64_val)

但读取char*类型的空终止字符串时,尝试了三种方法都得到垃圾值或无效结果,寻求正确的读取方式:

尝试过的三种方法

方法一

string_val := C.GoString((*C.char)(unsafe.Pointer(&(cValue.data[0]))))

方法二

var cString []byte
ptr := unsafe.Pointer(&(cValue.data[0]))

for {
    char := *(*C.char)(ptr)
    if char == 0 {
        break
    }
    cString = append(cString, byte(char))
    ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(char))
}

goString := string(cString)

方法三

cStringPtr := (*byte)(unsafe.Pointer(&(cValue.data[0])))
cString := unsafe.Slice(cStringPtr, 0)

// 转换为Go字符串
goString := string(cString)

正确的读取方法

问题核心是:联合体中的string_val本身是一个指针类型,你需要先读取这个指针的值,再用它访问字符串内容,而非直接把联合体的首地址当作字符串首地址。

方案1:直接访问联合体字段(如果Go绑定支持)

// 读取联合体中存储的char*指针
strPtr := (*C.char)(unsafe.Pointer(&(cValue.data.string_val)))
// 转换为Go字符串
goString := C.GoString(strPtr)

方案2:通过指针类型转换读取(适用于无法直接访问字段的场景)

// 获取联合体首地址(存储char*值的内存位置)
strPtrAddr := unsafe.Pointer(&(cValue.data[0]))
// 解引用得到真正的字符串指针
strPtr := *(*C.char)(strPtrAddr)
// 转换为Go字符串
goString := C.GoString(strPtr)

原错误逻辑是把联合体的首地址直接转换成*C.char,但这个地址里存储的是char*的指针值,而非字符串的首字节,所以必须先解引用拿到真正指向字符串的指针,再传递给C.GoString处理。

内容的提问来源于stack exchange,提问作者Abrar Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 17:17:44