Go🚀Advancedadvanced
CGo — Calling C from Go
Go · Advanced · Run with go run
Explanation
CGo lets Go packages call C code and be called from C. Import `"C"` (a pseudo-package) to access C types and functions. CGo compiles the C code in comments above `import "C"` and links it. CGo crossings (Go→C, C→Go) are expensive — batch calls when possible. CGo disables some Go optimizations and complicates cross-compilation.
Real-World Scenario
Wrapping a high-performance C library (e.g., a hardware crypto accelerator or a legacy C database engine) for use in Go services — CGo provides the bridge without rewriting the C library.
Quick Snippet
snippet.go
package main
/*
#include <stdlib.h>
#include <string.h>
char* repeat(const char* s, int n) {
int len = strlen(s);
char* result = malloc(len * n + 1);
for (int i = 0; i < n; i++) {
memcpy(result + i * len, s, len);
}
result[len * n] = '\0';
return result;
}
*/
import "C"
import "unsafe"
func Repeat(s string, n int) string {
cs := C.CString(s)
defer C.free(unsafe.Pointer(cs))
result := C.repeat(cs, C.int(n))
defer C.free(unsafe.Pointer(result))
return C.GoString(result)
}Full Example
cgo_basics.go
// Compile: go run cgo_basics.go (requires a C compiler + CGO_ENABLED=1)
// Output:
// C says: 42 doubled is 84
//
// CGo lets Go call C code. The C source lives in the comment block
// immediately above `import "C"` — there must be no blank line between
// the comment and the import.
package main
/*
#include <stdlib.h>
int double_it(int n) {
return n * 2;
}
*/
import "C"
import "fmt"
func main() {
n := C.int(42)
doubled := C.double_it(n)
fmt.Printf("C says: %d doubled is %d\n", int(n), int(doubled))
}
Run command
go run cgo_basics.go (requires a C compiler + CGO_ENABLED=1)