golang/go
cgo
cmd/cgo (in src/cmd/cgo/) is the bridge between Go and C. It is a preprocessor: when a Go package imports the special pseudo-package "C", the go command runs cgo first to translate the package's .go files into a mix of regular Go files and generated C glue files.
The runtime side of cgo lives in src/runtime/cgo/ and src/runtime/cgocall.go. Together they let Go call into C and vice versa.
Purpose
cgo solves three problems:
- Calling C from Go. A Go function calls into C; cgo generates the calling-convention adapter on both sides.
- Calling Go from C. The reverse — typically used for callbacks. cgo generates a Go-callable trampoline registered with the runtime.
- C type interop. Go code can declare variables of C types (
C.int,C.struct_foo,C.char), and cgo generates Go shadow types matching the underlying ABI.
How it works
graph TD
Source[foo.go with import "C"] --> Cgo[cmd/cgo]
CHeader[CGO_CFLAGS, // #include comments] --> Cgo
Cgo --> GoOut[_cgo_gotypes.go, _cgo_defun.c, _cgo_main.c, etc.]
GoOut --> Compile[cmd/compile + host C compiler]
Compile --> Link[cmd/link external mode]
Link --> BinaryStep-by-step for a package that uses cgo:
cmd/godetects animport "C"line.- It invokes
cmd/cgo, passing the Go source files plus any in-comment#cgodirectives:// #cgo CFLAGS: -DFOO=1 // #include <stdio.h> import "C" cmd/cgoparses the Go file, findsC.fooreferences, and generates several outputs in a temporary directory:_cgo_gotypes.go— Go declarations for every C type and function used._cgo_main.c,_cgo_export.c— C glue.- Modified
.gofiles whereC.foo(args)becomes_Cfunc_foo(args).
cmd/gothen compiles the generated Go files withcmd/compileand the C glue with the host C compiler.- The package archive contains both Go-compiled objects and C-compiled objects.
cmd/linklinks them, using external linkmode if the C side requires the host linker.
What cgocall does at runtime
When Go code calls a C function, control reaches runtime.cgocall (in src/runtime/cgocall.go):
- Save the current G's state.
- Switch to the M's
g0(system) stack. - Lock the M to the current OS thread (some C libraries require thread affinity).
- Call into the C function via
asmcgocall(per-arch assembly). - On return, swap back to the user G.
The reverse direction (C calls Go) goes through cgoCallback, which:
- Acquires a G (creates one if needed) on the calling thread.
- Switches from C to Go calling convention.
- Runs the Go callback.
- Returns control to the C caller.
These transitions are expensive relative to a normal Go function call, which is why cgo is reserved for "I really need C" cases, not for normal interop.
Directory layout
src/cmd/cgo/
├── doc.go # User-facing cgo manual ('go help cgo')
├── main.go # Entry: parse args, drive
├── ast.go # Walk Go AST for C.foo references
├── gcc.go # Invoke C compiler to extract types/decls
├── out.go # Emit Go and C glue files
├── godefs.go # Support 'godefs' mode
├── doc.go # Manual page
├── internal/
│ ├── test/ # cgo integration tests (programs)
│ ├── teststdio/, testtls/, ... # Specialized tests
│ └── ...
src/runtime/cgo/
├── cgo.go # Public symbols visible from cgo-emitted code
├── callbacks.go # Go ↔ C callback table
├── gcc_<os>.c # Host C glue per OS (signal handling, TLS, ...)
├── asm_<arch>.s # Per-arch trampolines
└── ...
src/runtime/cgocall.go # Runtime side of Go→C callsKey source files
| File | Purpose |
|---|---|
src/cmd/cgo/main.go |
cgo driver |
src/cmd/cgo/gcc.go |
Use the host C compiler to extract types |
src/cmd/cgo/out.go |
Emit generated Go and C glue (the largest cgo file) |
src/cmd/cgo/doc.go |
The cgo user manual; output of go doc cmd/cgo |
src/runtime/cgocall.go |
Go→C and C→Go runtime helpers |
src/runtime/cgo/asm_<arch>.s |
Per-arch trampolines |
src/runtime/cgo/callbacks.go |
Callback registration |
CGO flags
In a Go file, #cgo lines configure the C compile/link environment per-package:
// #cgo CFLAGS: -I${SRCDIR}/include
// #cgo LDFLAGS: -L${SRCDIR}/lib -lfoo
// #cgo darwin LDFLAGS: -framework Cocoa
// #cgo pkg-config: openssl
// #include "foo.h"
import "C"CGO_ENABLED=0 disables cgo entirely (and the build system removes any _cgo files from the build set).
CC, CC_FOR_TARGET, CXX_FOR_TARGET choose the C/C++ compilers. See src/make.bash for the full list.
Testing cgo
A substantial chunk of cgo correctness lives under src/cmd/cgo/internal/:
test/,testcarchive/,testcshared/— integration tests for various build modes.teststdio/,testtls/,testsanitizers/— specialized scenarios.testlife/,testfortran/, etc. — language interop and unusual languages.
These run as part of cmd/dist test (the cgo_test bucket).
Special considerations
- GC interaction. When Go code calls C, the Go GC must not move or reclaim Go objects whose pointers were passed across the boundary. The compiler's
cgocheck(cheap; default) andcgocheck2(GODEBUG=cgocheck=1/2, deeper) catch many violations.runtime.Pinner(insrc/runtime/pinner.go) lets you explicitly pin a Go object for cgo. - Linkmode. cgo usually forces
-linkmode=external(host linker), which is slower than internal linking but required for many C libraries. - Thread-locking. When entering C, the calling goroutine is locked to its OS thread. C code that calls back into Go gets a fresh G but the same thread.
- Signal handling. Cgo-enabled binaries have a more elaborate signal-handler dance (in
runtime/signal_*.goandruntime/cgo/gcc_*.c) to coexist with C libraries that install their own handlers.
Integration points
cmd/go(go-command) drives cgo invocation per package.cmd/compile(compiler) consumes the Go files cgo generates.cmd/link(linker) typically runs in external mode for cgo packages.runtime(runtime) provides the call-into-C and call-from-C primitives.net,os/user,crypto/internal/...— several standard library packages use cgo whenCGO_ENABLED=1for OS-native resolvers and crypto.
Entry points for modification
- Cgo bug in code generation: start in
src/cmd/cgo/out.go. Many bugs end up here. - Cgo runtime issue:
src/runtime/cgocall.goandsrc/runtime/cgo/asm_<arch>.s. - Adding a build mode for cgo: usually touches both
cmd/go,cmd/link, andruntime/cgo.
Where to read next
src/cmd/cgo/doc.go— the user-facing cgo manual.- Runtime — the GMP scheduler's interaction with cgo, signal handling.
- Linker — when external linking is required and how it differs.
- Go command — how cgo invocation fits into the build pipeline.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.