Noções Básicas de CGO
10 exemplos para você começar com CGO e Interop - 7 básicos e 3 intermediários.
Busque em todas as páginas da documentação
10 exemplos para você começar com CGO e Interop - 7 básicos e 3 intermediários.
gcc ou clang; Xcode CLI tools no macOS).go env CGO_ENABLED deve imprimir 1 quando um compilador estiver presente.mkdir cgodemo && cd cgodemo && go mod init example.com/cgodemo.CGO_ENABLED=0 go build ao testar alternativas.import "C" com um bloco de comentários C habilita o cgo para este arquivo.
package main
/*
#include <stdio.h>
*/
import "C"
func main() {
C.puts(C.CString("hello from cgo"))
}/* ... */ imediatamente acima de import "C" é passado para o compilador C.C.puts mapeia para a função da biblioteca padrão C.C.CString aloca memória C; código de produção deve usar defer C.free (abordado no exemplo 5).Relacionado: CGO: Cruzando a Fronteira Go-C - O custo do cgo em tempo de execução
O linking usa símbolos de libc incluídos via headers.
package main
/*
#include <math.h>
*/
import "C"
import "fmt"
func main() {
x := C.sqrt(2)
fmt.Println(float64(x))
}C.sqrt.float64(x) para APIs Go.LDFLAGS extra para libm na maioria das plataformas ao usar headers padrão.Relacionado: Chamando C de Go e Exportando Go para C - Conversões de tipo e diretivas
#cgo CFLAGS e #cgo LDFLAGSDiretivas no bloco de comentários configuram flags de compilação e linking.
package main
/*
#cgo CFLAGS: -Wall
#cgo LDFLAGS: -lm
#include <math.h>
*/
import "C"
func main() {
_ = C.cos(1)
}#cgo CFLAGS adiciona flags do compilador C apenas para este pacote.#cgo LDFLAGS passa flags para o linker (-lm inclui libm onde necessário).#cgo linux LDFLAGS: ou #cgo darwin CFLAGS:.Relacionado: Chamando C de Go e Exportando Go para C - Referência completa de diretivas
${SRCDIR} expande para o diretório que contém o arquivo Go.
package main
/*
#cgo CFLAGS: -I${SRCDIR}/include
#include "greet.h"
*/
import "C"
func main() {
C.greet_from_c()
}include/greet.h e greet.c (ou um .a pré-compilado) ao lado do arquivo Go.#cgo LDFLAGS: ${SRCDIR}/greet.o ao compilar um .c local no pacote.Relacionado: Boas Práticas de CGO e Interoperabilidade - Isole o cgo por trás de pacotes pequenos
C.CString e C.freeAlocações C não são coletadas pelo garbage collector do 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("freed after use")
}C.CString copia bytes e adiciona um terminador NUL no heap C.C.free a menos que C assuma a propriedade de acordo com o contrato da API.unsafe apenas para a conversão unsafe.Pointer necessária para C.free.Relacionado: Segurança de FFI: Ponteiros, C.CString e Free - Regras de propriedade em profundidade
[]byte do Go para CUse C.CBytes para buffers binários e libere quando terminar.
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 aloca len(data) bytes; o conteúdo é copiado.C.GoBytes copia a memória C de volta para uma slice Go.Relacionado: Segurança de FFI: Ponteiros, C.CString e Free - Passagem de slices e ponteiros
Envie um stub quando 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 compilam apenas quando o cgo está habilitado.!cgo permitem que CI e compilações cruzadas sejam bem-sucedidas sem um compilador C.Relacionado: syscall e Alternativas Pure-Go para CGO - Estratégias de fallback
CGO_CFLAGS e CGO_LDFLAGSSubstitua flags globalmente para uma única compilação sem editar o código-fonte.
CGO_CFLAGS="-O3 -I/opt/vendor/include" \
CGO_LDFLAGS="-L/opt/vendor/lib -lvendor" \
go build -o app .CGO_CFLAGS e CGO_LDFLAGS são anexados às linhas #cgo por pacote.Relacionado: Boas Práticas de CGO e Interoperabilidade - Hábitos de compilação reproduzíveis
Use restrições de compilação em testes e pequenos pacotes de sondagem.
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("cgo enabled:", 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 arquivos com tags em vez de analisar go env em tempo de execução.Relacionado: Guia de Decisão de Interop: CGO vs RPC vs Rewrite - Quando o cgo vale o custo de compilação
Oculte import "C" atrás de um pacote 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 Go puro.native com tags de compilação enquanto fuzzing a lógica em wrappers Go puros.error do Go nesta fronteira.Relacionado: Chamando C de Go e Exportando Go para C - Exportando Go de volta para C
Versões da Stack: Esta página foi escrita para Go 1.26.x (GC padrão Green Tea, modernizadores go fix - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação) e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 18 de jul. de 2026