
CGO简介与数据类型转换基础
go语言通过cgo机制提供了与c语言代码进行互操作的能力,使得开发者可以在go项目中调用c函数或使用c库。这种互操作性在需要利用现有c代码库、进行系统级编程或优化性能时尤为重要。然而,cgo编程的核心挑战之一在于go与c之间的数据类型转换与内存管理。
在Go和C之间进行数据传递时,必须进行适当的类型转换。CGO提供了一系列内置函数和规则来简化这一过程。理解这些规则是编写健壮CGO代码的关键。
- 基本类型转换: CGO会自动处理大部分基本数值类型(如int, float, double)的转换。Go中的int、float32、float64等可以直接映射到C的对应类型。例如,C.int(goInt)将Go的int转换为C的int。
- 指针类型: CGO对指针的处理较为严格。Go不能直接操作C的任意指针,反之亦然。通常需要通过unsafe.Pointer进行显式转换,但在大多数情况下,CGO会提供更安全的封装。
- 字符串与切片: 这是最常见的转换场景之一,也是本教程的重点。
C char* 到 Go 字符串/切片
当C函数返回一个C风格的字符串(char*)时,Go语言需要将其转换为Go的string类型或[]byte切片。
1. 转换为Go string
CGO提供了C.GoString()函数,用于将C的char*(以null结尾的字符串)转换为Go的string。
C代码示例 (test.c):
立即学习“go语言免费学习笔记(深入)”;
#include// For malloc and free #include // For strcpy // 返回一个静态字符串字面量 char* GetStaticString() { return "Hello, Go (Static)"; } // 返回一个动态分配的字符串,需要Go侧释放 char* GetDynamicString() { char* msg = (char*)malloc(sizeof(char) * 12); // "Hello, Go\0" if (msg == NULL) return NULL; strcpy(msg, "Hello, Go"); return msg; }
Go代码示例 (main.go):
package main /* #include// For C.free // 声明C函数,假设它们在单独的test.c文件中 char* GetStaticString(); char* GetDynamicString(); */ import "C" import ( "fmt" "unsafe" // For unsafe.Pointer and C.free ) func main() { // 示例1: C函数返回静态字符串字面量 cStaticString := C.GetStaticString() goStaticString := C.GoString(cStaticString) fmt.Printf("C.GetStaticString() -> Go String: \"%s\"\n", goStaticString) // 静态字符串字面量无需释放 // 示例2: C函数返回动态分配的字符串 cDynamicString := C.GetDynamicString() goDynamicString := C.GoString(cDynamicString) fmt.Printf("C.GetDynamicString() -> Go String: \"%s\"\n", goDynamicString) // 动态分配的内存必须在Go侧手动释放 C.free(unsafe.Pointer(cDynamic











