Conceptos básicos de CGO
10 ejemplos para empezar con CGO e Interop: 7 básicos y 3 intermedios.
Busca en todas las páginas de la documentación
10 ejemplos para empezar con CGO e Interop: 7 básicos y 3 intermedios.
gcc o clang; herramientas de línea de comandos de Xcode en macOS).go env CGO_ENABLED debería imprimir 1 cuando un compilador está presente.mkdir cgodemo && cd cgodemo && go mod init example.com/cgodemo.CGO_ENABLED=0 go build al probar alternativas.import "C" con un bloque de comentarios C habilita cgo para este archivo.
package main
/*
#include <stdio.h>
*/
import "C"
func main() {
C.puts(C.CString("hola desde cgo"))
}/* ... */ inmediatamente encima de import "C" se pasa al compilador C.C.puts se mapea a la función de la biblioteca estándar C.C.CString asigna memoria C; el código de producción debería usar defer C.free (cubierto en el ejemplo 5).Relacionado: CGO: Cruzando el límite Go-C - El coste de cgo en tiempo de ejecución
El enlazado utiliza símbolos de libc incluidos a través de cabeceras.
package main
/*
#include <math.h>
*/
import "C"
import "fmt"
func main() {
x := C.sqrt(2)
fmt.Println(float64(x))
}C.sqrt.float64(x) para las APIs de Go.LDFLAGS adicionales para libm en la mayoría de las plataformas cuando se usan cabeceras estándar.Relacionado: Llamar a C desde Go y Exportar Go a C - Conversiones de tipos y directivas
#cgo CFLAGS y #cgo LDFLAGSLas directivas en el bloque de comentarios configuran las banderas de compilación y enlace.
package main
/*
#cgo CFLAGS: -Wall
#cgo LDFLAGS: -lm
#include <math.h>
*/
import "C"
func main() {
_ = C.cos(1)
}#cgo CFLAGS añade banderas del compilador C solo para este paquete.#cgo LDFLAGS pasa banderas al enlazador (-lm incluye libm cuando es necesario).#cgo linux LDFLAGS: o #cgo darwin CFLAGS:.Relacionado: Llamar a C desde Go y Exportar Go a C - Referencia completa de directivas
${SRCDIR} se expande al directorio que contiene el archivo fuente Go.
package main
/*
#cgo CFLAGS: -I${SRCDIR}/include
#include "greet.h"
*/
import "C"
func main() {
C.greet_from_c()
}include/greet.h y greet.c (o un archivo .a precompilado) junto al archivo Go.#cgo LDFLAGS: ${SRCDIR}/greet.o al compilar un archivo .c local en el paquete.Relacionado: Mejores prácticas de CGO e Interoperabilidad - Aislar cgo detrás de paquetes pequeños
C.CString y C.freeLas asignaciones de C no son recolectadas por el garbage collector de Go.
package main
/*
#include <stdlib.h>
#include <stdio.h>
*/
import "C"
import "unsafe"
func printC(s string) {
cs := C.CString(s)
defer C.free(unsafe.Pointer(cs))
C.puts(cs)
}
func main() {
printC("liberado después de su uso")
}C.CString copia bytes y añade un terminador NUL en el heap de C.C.free a menos que C tome posesión según el contrato de la API.unsafe solo para la conversión unsafe.Pointer requerida por C.free.Relacionado: Seguridad FFI: Punteros, C.CString y Free - Reglas de propiedad en profundidad
[]byte de Go a CUsa C.CBytes para buffers binarios y libera cuando termines.
package main
/*
#include <stdlib.h>
#include <string.h>
*/
import "C"
import "unsafe"
func main() {
data := []byte{0x01, 0x02, 0x03}
ptr := C.CBytes(data)
defer C.free(ptr)
_ = C.memcpy(ptr, ptr, C.size_t(len(data)))
}C.CBytes asigna len(data) bytes; se copian los contenidos.C.GoBytes copia la memoria C de vuelta a un slice de Go.Relacionado: Seguridad FFI: Punteros, C.CString y Free - Paso de slices y punteros
Envía un stub cuando CGO_ENABLED=0.
//go:build cgo
package demo
/*
#include <stdint.h>
*/
import "C"
func AddOne(n int) int {
return int(C.int(n) + 1)
}//go:build !cgo
package demo
func AddOne(n int) int {
return n + 1
}//go:build cgo solo compilan cuando cgo está habilitado.!cgo permiten que CI y las compilaciones cruzadas tengan éxito sin un compilador C.Relacionado: syscall y Alternativas Go Puras a CGO - Estrategias de respaldo
CGO_CFLAGS y CGO_LDFLAGSSobrescribe las banderas globalmente para una sola compilación sin editar el código fuente.
CGO_CFLAGS="-O3 -I/opt/vendor/include" \
CGO_LDFLAGS="-L/opt/vendor/lib -lvendor" \
go build -o app .CGO_CFLAGS y CGO_LDFLAGS se añaden a las líneas #cgo por paquete.Relacionado: Mejores prácticas de CGO e Interoperabilidad - Hábitos de compilación reproducibles
Usa restricciones de compilación en pruebas y pequeños paquetes de sondeo.
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("cgo habilitado:", cgoEnabled())
fmt.Println("GOOS/GOARCH:", runtime.GOOS, runtime.GOARCH)
}//go:build cgo
package main
func cgoEnabled() bool { return true }//go:build !cgo
package main
func cgoEnabled() bool { return false }cgoEnabled entre archivos etiquetados en lugar de analizar go env en tiempo de ejecución.Relacionado: Guía de Decisión de Interoperabilidad: CGO vs RPC vs Reescribir - Cuándo cgo vale el coste de compilación
Oculta import "C" detrás de un paquete interno.
// internal/native/add.go
package native
/*
#include "add.h"
*/
import "C"
func Sum(a, b int) int {
return int(C.add(C.int(a), C.int(b)))
}// main.go
package main
import (
"fmt"
"example.com/cgodemo/internal/native"
)
func main() {
fmt.Println(native.Sum(40, 2))
}internal/native importa C; main permanece en Go puro.native con etiquetas de compilación mientras se exploran las lógicas en wrappers Go puros.error de Go en este límite.Relacionado: Llamar a C desde Go y Exportar Go a C - Exportar Go de vuelta a C
Versiones de la pila: Esta página fue escrita para Go 1.26.x (GC por defecto Green Tea, modernizadores de go fix - verifica el parche en la compilación), chi (última versión - verifica en la compilación), gin (última versión - verifica en la compilación), echo (última versión - verifica en la compilación), google.golang.org/grpc (última versión - verifica en la compilación), sigs.k8s.io/controller-runtime (última versión - verifica en la compilación), kubebuilder (última versión - verifica en la compilación), tinygo (última versión - verifica objetivos de placa en la compilación), wazero (última versión - verifica en la compilación) y golangci-lint (última versión - verifica el conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 18 jul 2026