Limitations: where the seams are

So you’re about to point go2cs at your own Go code. Before you spend an evening on it, here is where it will fail, where it will fight you, and where it will quietly do something a little different from Go – better you hear it from me than from a stack trace. Specific bugs with workarounds live in Known issues. This page is the limits that come with running Go on .NET, plus the rough spots real code hits today.

The short version

Good odds tonight: pure Go that builds with Go 1.24 and CGO_ENABLED=0, leans mostly on the standard library, and runs on x64 Windows or Linux. A longer evening: lots of third-party modules, unsafe, assembly fast paths, or tests that pull in testify or read os.Args.

What won’t make the trip

What converts, but doesn’t behave exactly like Go

What works, but costs you something

Third-party modules: where they trip today

The validated modules page is still short.

Note – known today, and temporary. These converter bugs are being worked through and may be resolved in a future release: an exported alias of an unexported type used from another package (CS0122; logrus and testify each have one), a parenthesized type in a type assertion, a function-local pointer type used as a conversion, a defined type over another package’s type used as a conversion, and a promoted method with a parameter named target. One more is silent rather than a compile error: a method on a named map type that has the name and parameters of a map operation the runtime library also provides (Add(key, value), Remove(key), Clear(), ContainsKey(key), and Send(value) on a named channel type) loses to the library’s member, so the Go method does not run.

What “validated” means, and what it doesn’t

A package’s own Go Test functions were converted, run, and compared with go test verdict for verdict, by full test name. That’s a real bar, and narrower than the word sounds:

Platforms and toolchain

Reading and debugging the output

What you might expect to break, and doesn’t

The language itself (generics, closures, struct embedding, range-over-func, typed nil pointers in interfaces, randomized map order), defer/panic/recover, channels and select, reflect (encoding/json and text/template pass their own suites on it), and net/http with HTTP/2 and crypto/tls over real sockets.

When you hit a seam

  1. Start from a clean Go build: GOTOOLCHAIN=local, then go build ./... for the same OS and tags.
  2. Read the conversion’s warnings and its summary line, not the exit code.
  3. A clean build that throws NotImplementedException wants a pure-Go build tag. A C# compile error in converted code is a converter bug until proven otherwise.
  4. A behavior difference in the standard library? Check the package’s disclosures on Validated Test Packages.
  5. Check Known issues, then open an issue with the output of go2cs -version, your OS, the error text, and the smallest Go that reproduces it.

If you find a seam that isn’t on this page, that’s the one I most want to hear about.