Skip to content

Latest commit

 

History

History
175 lines (135 loc) · 10.4 KB

FAQ.md

File metadata and controls

175 lines (135 loc) · 10.4 KB

Frequently asked questions

Short, direct answers for a Go developer or a C# developer meeting go2cs for the first time. Each answer links to the page that has the detail. The limits are collected in Limitations, and specific bugs with their workarounds are in Known issues.

Why convert Go to C#?

Mostly to use Go code from inside .NET. When the library you need is written in Go, the usual choices are a separate process, a native wrapper, or a hand rewrite that has to be kept in step forever. go2cs adds another: convert it, and call it as managed code. Converted code is also a way to run a Go program anywhere .NET runs, and because the C# mirrors the Go, a way to learn one language from the other. Background has the longer answer.

If you write Go and have no .NET in your life, go2cs gives you nothing Go does not already do better. It is for the place where the two meet.

Is converted code slower than Go?

Usually, yes. Most compute lands within a small multiple of Go's time, string-heavy work takes several times longer, and maps run at parity with Go or better. Asking at run time whether a value satisfies an interface is the slowest thing converted code does. A converted program also starts slower and uses more memory than the Go it came from. The performance comparison has the measurements and says which machine and platform produced them. Some optimization is already in, such as stack strings and stack slices, and the Roadmap lists the work planned to narrow the gap.

Does converted code really behave like Go?

That is measured, not claimed. Each standard-library package's own Go test suite is converted to C#, run, and compared with go test, verdict for verdict, on Windows and Linux. A difference is never hidden: it is disclosed by name, with its reason, on the package's row in Validated Test Packages. What "validated" means, and what it doesn't says what that proves.

Some things do differ, and you should know them before you start. A goroutine is an operating-system thread, so thousands are fine and hundreds of thousands are not. A deadlock usually hangs where Go would report it. A goroutine's stack does not grow. What converts, but doesn't behave exactly like Go lists them all.

What does not convert?

  • cgo. A package that imports "C" is refused, by name, and the run stops (the plan).
  • Hand-written assembly. A function whose body lives in a .s file becomes a stub that throws when it is called. Many libraries ship a pure-Go fallback behind a build tag, and converting with that tag is the usual answer.
  • Code that needs a newer Go than go2cs tracks. The converter refuses it and names both releases.
  • One form of generic type alias, an alias of an anonymous struct or interface.

What won't make the trip has the detail and the workarounds.

Which Go and .NET versions does it use?

Exactly one Go release and one .NET release at a time, both named in the README's Requirements. The Go release it tracks today is out of upstream support, so the converted standard library carries none of the Go security fixes issued since. The Roadmap says which Go releases come next and in what order.

Which platforms are supported?

Windows and Linux on x64, where the converted standard library is validated against Go's own tests. macOS, on Intel and Apple silicon, has packages and is being validated package by package; a row on the roster shows a macOS count once its package validates there. One conversion targets one operating system, so you convert once for each. Platforms has the rest.

What does the generated C# look like?

Like the Go, on purpose. A Go method is a C# extension method, multiple results are a tuple, and an embedded struct's fields are promoted. Names keep Go's spelling, so they do not follow .NET naming conventions, and a few Go ideas with no C# spelling use letters you will not find on your keyboard, such as ж<T> for a pointer. The glyph table explains each one. To judge it on real code, see Real standard-library conversions, side by side: converted files beside their Go source, from simple to complex.

It is readable, and it is still generated code. Do not edit a converted file by hand, because the next conversion rewrites it: change the Go, or mark a file as manually converted so the converter leaves it alone. You debug the C#, with breakpoints and stepping on the generated files. Reading and debugging the output covers this, and the Tour of go2cs shows Go and its C# side by side.

How do I call a converted Go package from C#?

Reference it like any other library. A Go package becomes a .NET assembly: a published one is a NuGet PackageReference, and one you convert yourself is a ProjectReference. Go's strings, slices, maps, errors and multiple results each have a C# shape, and Consuming converted Go from C# shows every one with working code, rough edges included. The road runs one way: Go source cannot call a .NET API.

Why not call Go through a native library instead?

You can, and if you need Go's own speed it is the better choice: export the Go functions as C, build a native library, and import it with P/Invoke. The cost is a native binary to build and ship for every platform, a C toolchain, two runtimes and two garbage collectors in one process, and a boundary where every string and slice is copied or pinned. Converted code is managed code in one runtime. It builds with dotnet build, deploys as part of your application, and you can step into it in the debugger. It is slower than native Go, and that is the trade.

Can it convert a module with third-party dependencies?

Yes. go2cs -recurse=nuget converts a module and every third-party package it imports, in dependency order, and writes a solution that restores and builds (Converting a real-world Go module). Not every module converts cleanly yet. A dependency that uses assembly or unsafe shortcuts may need its pure-Go build tag, and real code still turns up converter bugs. When one dependency blocks you, -recurse=module,nuget converts your own packages first. Third-party modules: where they trip today is the honest list, and Validated Modules names the modules that pass their own tests.

Does it work with Native AOT?

It runs, and it costs you. A converted program can be published with Native AOT and starts much faster than the same program under the JIT. The publish itself is slow and the executable is large, because every converted package the program references is compiled in full, and once running the program is slower than the JIT on most measurements. Known issues has the measured cost and the platform it was measured on, and the Roadmap has the work under way to reduce it.

What does converted code depend on at run time?

Three kinds of NuGet package, all open source: the runtime library (go.lib), the converted standard-library packages your code imports (go.<package>), and the source generators (go.gen), which run only when you compile. They are built and versioned together, so a project uses one version of all of them. A converted program needs the .NET runtime, or you publish it self-contained. It does not need Go installed to run. You need Go only to convert.

What license covers the code go2cs generates?

Not the converter's. LICENSING.md is the authority, and says, under Generated output:

Code generated by go2cs is not subject to the go2cs converter's AGPL license merely because it was produced by go2cs. Rights in generated output remain governed by the rights applicable to the input source and any separately licensed components incorporated into or referenced by the output. src/go2cs/LICENSE-EXCEPTION states this as a binding additional permission.

And of the converter's own license:

The public converter grant is AGPL-3.0-only, not “or later.” The full text is in src/go2cs/LICENSE and LICENSES/AGPL-3.0-only.txt. The copyright holders grant one additional permission under AGPL section 7: the go2cs Converter Output Exception in src/go2cs/LICENSE-EXCEPTION, which states that the converter's output is never a covered work merely because go2cs produced it and carries the MIT grant for the embedded templates and other original scaffolding reproduced in that output.

The same page's table gives the rest: the runtime library and the source generators are MIT, and the converted standard library is BSD-3-Clause, with Go's upstream notices.

Running the converter, locally or in your own build, triggers no AGPL obligation; see the README's License section.

Can it convert C# to Go?

No. A source conversion from C# to Go would need so many restrictions on the C# that it would not be practical. To call compiled .NET code from Go instead, see go-dotnet, which hosts the .NET runtime, or embedding Mono through cgo.

Why does Go stop with "unexpected NUL in input"?

The Go file is not UTF-8. It is almost always a file made in Windows PowerShell 5.1 with > or Out-File, which write UTF-16, and then edited in place. Go source must be UTF-8, so go build fails before go2cs is involved at all. The walkthrough's note shows how to create the file as UTF-8 and a one-line command that re-saves a file that is already UTF-16.