Cgo lets Go packages call C code. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into a single Go package.

To lead with an example, here's a Go package that provides two functions - Random and Seed - that wrap C's random and srandom functions.

{{code "/doc/progs/cgo1.go" `/package rand/` `/END/`}}

Let’s look at what's happening here, starting with the import statement.

The rand package imports "C", but you'll find there's no such package in the standard Go library. That's because C is a "pseudo-package", a special name interpreted by cgo as a reference to C's name space.

The rand package contains four references to the C package: the calls to C.random and C.srandom, the conversion C.uint(i), and the import statement.

The Random function calls the standard C library's random function and returns the result. In C, random returns a value of the C type long, which cgo represents as the type C.long. It must be converted to a Go type before it can be used by Go code outside this package, using an ordinary Go type conversion:

{{code "/doc/progs/cgo1.go" `/func Random/` `/STOP/`}}

Here’s an equivalent function that uses a temporary variable to illustrate the type conversion more explicitly:

{{code "/doc/progs/cgo2.go" `/func Random/` `/STOP/`}}

The Seed function does the reverse, in a way. It takes a regular Go int, converts it to the C unsigned int type, and passes it to the C function srandom.

{{code "/doc/progs/cgo1.go" `/func Seed/` `/END/`}}

Note that cgo knows the unsigned int type as C.uint; see the cgo documentation for a complete list of these numeric type names.

The one detail of this example we haven't examined yet is the comment above the import statement.

{{code "/doc/progs/cgo1.go" `/\/\*/` `/STOP/`}}

Cgo recognizes this comment and uses it as a header when compiling the C parts of the package. In this case it is just a simple include statement, but it can be any valid C code. The comment must be immediately before the line that imports "C", without any intervening blank lines, just like a documentation comment.

Strings and things

Unlike Go, C doesn’t have an explicit string type. Strings in C are represented by a zero-terminated array of chars.

Conversion between Go and C strings is done with the C.CString, C.GoString, and C.GoStringN functions. These conversions make a copy of the string data.

This next example implements a Print function that writes a string to standard output using C's fputs function from the stdio library:

{{code "/doc/progs/cgo3.go" `/package print/` `/END/`}}

Memory allocations made by C code are not known to Go's memory manager. When you create a C string with C.CString (or any C memory allocation) you must remember to free the memory when you’re done with it by calling C.free.

The call to C.CString returns a pointer to the start of the char array, so before the function exits we convert it to an unsafe.Pointer and release the memory allocation with C.free. A common idiom in cgo programs is to defer the free immediately after allocating (especially when the code that follows is more complex than a single function call), as in this rewrite of Print:

{{code "/doc/progs/cgo4.go" `/func Print/` `/END/`}}

Building cgo packages

To build cgo packages, just use " go build" or "go install " as usual. The go tool recognizes the special "C" import and automatically uses cgo for those files.

More cgo resources

The cgo command documentation has more detail about the C pseudo-package and the build process. The cgo examples in the Go tree demonstrate more advanced concepts.

For a simple, idiomatic example of a cgo-based package, see Russ Cox’s gosqlite. Also, the Go Project Dashboard lists several other cgo packages.

Finally, if you’re curious as to how all this works internally, take a look at the introductory comment of the runtime package’s cgocall.c.