CodeNebula
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)