Golang / Golang Internals and Memory Management Interview Questions
What is cgo in Go and what are its performance trade-offs?
cgo allows Go programs to call C functions and vice versa. It is used for binding to C libraries (OpenSSL, SQLite, CUDA), OS system calls not exposed in the Go standard library, and legacy C codebases.
// Simple cgo example package main // #include // #include // char* greet(const char* name) { // char* result = malloc(100); // snprintf(result, 100, "Hello, %s!", name); // return result; // } import "C" import ( "fmt" "unsafe" ) func main() { cname := C.CString("World") // Go string â C string (malloc) defer C.free(unsafe.Pointer(cname)) // must free C memory! cresult := C.greet(cname) // call C function result := C.GoString(cresult) // C string â Go string (copy) C.free(unsafe.Pointer(cresult)) fmt.Println(result) // Hello, World! } // cgo overhead per call: // 60-200 ns per C call (vs ~1 ns for a plain Go function call) // The runtime must save goroutine state, switch stack frames, etc. // Cross-compilation challenge: // CGO_ENABLED=0 disables cgo and allows full static binary cross-compilation // CGO_ENABLED=1 (default) requires a C compiler on the target platform // Alternatives to cgo: // - Pure Go implementations (avoid cgo entirely) // - WASI / WebAssembly for sandboxed native code // - gRPC subprocess calling a C binary
Key costs of cgo: (1) each C call is ~60–200 ns overhead — avoid calling C in tight loops. (2) goroutines calling C must have the C function run on an OS thread — the Go scheduler complexity increases. (3) C memory is not managed by the Go GC — you must explicitly free it. (4) cross-compilation is much harder with cgo enabled.
More Related questions...