Skip to content
⚖️ A tool for transpiling C to Go.
Go Shell
Branch: master
Clone or download


Type Name Latest commit message Commit time
Failed to load latest commit information.
.snapshots Also use clang flags for ast command. Fixes #650 (#651) Apr 2, 2018
ast ast: support forward declarations of enums (#853) Apr 16, 2020
cc Load fileCache on Windows. Fixes #775 (#776) Jun 27, 2018
darwin Use pointers instead of interface/slice. Fixes #748 (#754) Jun 25, 2018
examples Move some files into examples/ May 30, 2017
noarch Support incrementing a MemberExpr that is is a pointer. Fixes #811 (#812 Dec 4, 2018
preprocessor Function definition by C include header list. Fixes #237 (#627) Feb 14, 2018
program Bump version: v0.26.0 Erbium 2020-03-17 Mar 17, 2020
tests Support incrementing a MemberExpr that is is a pointer. Fixes #811 (#812 Dec 4, 2018
transpiler ast,transpile: add support for ConstantExpr (#850) Mar 17, 2020
travis Remove triangle from CI. Fixes #756 (#774) Jun 29, 2018
types Add more simpleResolveTypes. (#810) Dec 2, 2018
util Use pointers instead of interface/slice. Fixes #748 (#754) Jun 25, 2018
.codeclimate.yml Adding codeclimate config May 4, 2017
.gitattributes Ignore testing code in GitHub statistics (#324) Nov 5, 2017
.gitignore Added support for nested structures. Fixes #114 (#341) Nov 12, 2017
.travis.yml Explicitly specify to use go v1.9.x for Travis CI. Fixes #752 (#753) Jun 17, 2018 Create Jul 7, 2017
LICENSE Adding @kamphaus as a major contributor (#755) Jun 19, 2018 Fix a few minor things (#786) Aug 29, 2018
cli_test.go Use stringer interface for snapshots instead of []string (#446) Dec 11, 2017
codecov.yml Adding custom codecov file so that it doesnt fail when coverage goes … Apr 26, 2017
go.mod Add go.mod and go.sum (#801) Nov 11, 2018
go.sum Add go.mod and go.sum (#801) Nov 11, 2018
main_test.go Remove GOPATH check. Fixes #797 (#814) Dec 30, 2018

Build Status GitHub version Go Report Card codecov GitHub license Join the chat at Twitter GoDoc

A tool for converting C to Go.

The goals of this project are:

  1. To create a generic tool that can convert C to Go.
  2. To be cross platform (linux and mac) and work against as many clang versions as possible (the clang AST API is not stable).
  3. To be a repeatable and predictable tool (rather than doing most of the work and you have to clean up the output to get it working.)
  4. To deliver quick and small version increments.
  5. The ultimate milestone is to be able to compile the SQLite3 source code and have it working without modification. This will be the 1.0.0 release.


c2go requires Go 1.9 or newer.

go get -u


c2go transpile myfile.c

The c2go program processes a single C file and outputs the translated code in Go. Let's use an included example, prime.c:

#include <stdio.h>
int main()
   int n, c;
   printf("Enter a number\n");
   scanf("%d", &n);
   if ( n == 2 )
      printf("Prime number.\n");
       for ( c = 2 ; c <= n - 1 ; c++ )
           if ( n % c == 0 )
       if ( c != n )
          printf("Not prime.\n");
          printf("Prime number.\n");
   return 0;
c2go transpile prime.c
go run prime.go
Enter a number
Prime number.

prime.go looks like:

package main

import "unsafe"

import ""

// ... lots of system types in Go removed for brevity.

var stdin *noarch.File
var stdout *noarch.File
var stderr *noarch.File

func main() {
	var n int
	var c int
	noarch.Printf([]byte("Enter a number\n\x00"))
	noarch.Scanf([]byte("%d\x00"), (*[1]int)(unsafe.Pointer(&n))[:])
	if n == 2 {
		noarch.Printf([]byte("Prime number.\n\x00"))
	} else {
		for c = 2; c <= n-1; func() int {
			c += 1
			return c
		}() {
			if n%c == 0 {
		if c != n {
			noarch.Printf([]byte("Not prime.\n\x00"))
		} else {
			noarch.Printf([]byte("Prime number.\n\x00"))

func __init() {
	stdin = noarch.Stdin
	stdout = noarch.Stdout
	stderr = noarch.Stderr

How It Works

This is the process:

  1. The C code is preprocessed with clang. This generates a larger file (pp.c), but removes all the platform-specific directives and macros.

  2. pp.c is parsed with the clang AST and dumps it in a colourful text format that looks like this. Apart from just parsing the C and dumping an AST, the AST contains all of the resolved information that a compiler would need (such as data types). This means that the code must compile successfully under clang for the AST to also be usable.

  3. Since we have all the types in the AST it's just a matter of traversing the tree in a semi-intelligent way and producing Go. Easy, right!?


By default only unit tests are run with go test. You can also include the integration tests:

go test -tags=integration ./...

Integration tests in the form of complete C programs that can be found in the tests directory.

Integration tests work like this:

  1. Clang compiles the C to a binary as normal.
  2. c2go converts the C file to Go.
  3. The Go is built to produce another binary.
  4. Both binaries are executed and the output is compared. All C files will contain some output so the results can be verified.


Contributing is done with pull requests. There is no help that is too small! :)

If you're looking for where to start I can suggest finding a simple C program (like the other examples) that does not successfully translate into Go.

Or, if you don't want to do that you can submit it as an issue so that it can be picked up by someone else.

You can’t perform that action at this time.