Open-source project
MadAppGang/dingo avatar
MadAppGang/dingo

Dingo: a Go meta-language with Result types, ? propagation and pattern matching

A meta-language for Go that adds Result types, error propagation (?), and pattern matching while maintaining 100% Go ecosystem compatibility

1,911 stars40 forksGoNOASSERTION

At a glance

What is it?
Dingo transpiles an extended Go dialect into plain Go. It adds sum types, exhaustive match, safe navigation and functional helpers, but the README does not document rollback or migration paths, so adoption stays a per-file decision.
Who is it for?
Dingo is for Go teams that want Result types, exhaustive match and safe navigation while keeping the compiled output as ordinary Go, and that can accept building the compiler from source. It is not for teams that need a documented rollback path or a stable v1.0, since the README targets v1.0 in Q1 2026 and the latest tagged release is v0.9.0 from 2026-01-08.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 21 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Dingo adds to Go, and who it is aimed at

Dingo is a meta-language: you write a Go-like dialect and a compiler emits ordinary Go. The README frames it as "Think TypeScript, but for Go", and the repository layout backs that up. There is a cmd/ directory for the compiler binary, a pkg/ directory, a runtime/ directory, and a features/ directory, alongside example projects numbered from 01_error_propagation through 15_cli_framework. The pitch is aimed at Go developers who are tired of repeating `if err != nil` and who want the ergonomics Rust developers take for granted, without giving up the Go toolchain, gopls, or the runtime they already deploy.

The feature set is concrete rather than aspirational. The README's status line lists sum types, pattern matching, error propagation, tuples and safe navigation as working. The examples directory mirrors that list: 02_result, 03_option, 04_pattern_matching, 05_sum_types, 07_tuples, 08_safe_navigation, 10_null_coalesce and 12_guard each have their own folder. If you want to judge the language before reading any prose, that directory tree is the honest summary of what exists.

Who is it not for? Anyone who needs a language with a committee behind it, a published specification, or a compatibility promise. The README itself calls the project a "Playground for Go's Future" and sets a v1.0 target of Q1 2026, which tells you the authors see the current state as pre-stable.

How the transpiler works: source maps, gopls proxy and the plugin story

The mechanism is transpilation, not a new runtime. Dingo source compiles to Go source, and the README is explicit that the result is "clean, idiomatic Go code" with "zero runtime overhead" and "zero new dependencies". There is no Dingo virtual machine to ship, and the compiled binary is a Go binary.

The toolchain around that core is where the design gets interesting. The repository depends on go.lsp.dev/protocol, go.lsp.dev/jsonrpc2 and go.lsp.dev/uri, which means Dingo ships its own language server rather than only a command line compiler. The README describes Phase 10 as complete with a "LSP integration with gopls proxy" and auto-rebuild on save. The proxy detail matters: instead of reimplementing Go's analysis, Dingo forwards to gopls and layers its own understanding of the extended syntax on top. The topics list on the repository includes gopls, language-server and lsp, which is consistent with that.

Source maps are named in the README as one of the things Dingo adds over Borgo, the project it credits as proving the transpile-to-Go approach. For a developer this is the difference between a compile error pointing at generated Go and one pointing at the line you actually wrote. The README does not spell out the source map format, so treat that as something to confirm by triggering an error.

The configuration file is dingo.toml, with a dingo.toml.example in the repository root. The README's framing of plugins is deliberately loose: "Disable all plugins? You're running pure Go." That sentence is the whole documented story on plugin configuration in the README, so if feature toggling is central to your adoption, read dingo.toml.example rather than the README.

Installing Dingo and running your first file

There is no published package or installer in the README. The documented path is to clone the repository and build the compiler from source, which means you need a Go toolchain first. Note that go.mod declares go 1.25.4 even though the README badge says Go 1.21+, so check your installed version against the module file before you start.

The README gives these commands to obtain and build the compiler:

bash
git clone https://github.com/MadAppGang/dingo.git
cd dingo
go build -o dingo ./cmd/dingo
export PATH=$PATH:$(pwd)

After that, the dingo binary sits in the repository root and the PATH export makes it callable from anywhere in the shell session. If the build fails, the most likely cause is a Go version below the one declared in go.mod.

The first program the README shows is deliberately plain, so you can confirm the pipeline before touching any new syntax. Create hello.dingo with a package clause, an import of fmt, and a main function that prints a string. Then use one of three subcommands:

bash
dingo build hello.dingo
dingo run hello.dingo
dingo go hello.dingo

The README maps these onto Go's own verbs: build transpiles and compiles to a binary, run transpiles and executes immediately, and go emits .go files without compiling. For a first real test, `dingo go` is the useful one, because it leaves the generated Go on disk where you can read it and diff it against what you would have written by hand. That generated file is the artefact your team has to accept, not the Dingo source.

Sum types, match and the ? operator in practice

The README's worked example declares an enum with two variants, one carrying an int and one a string, then matches on the result. The syntax is close enough to Go that the shape is readable at a glance, but the semantics are not Go's. The enum keyword introduces a closed set of variants, and match is checked for exhaustiveness, which the README lists as a feature. That is the part Go cannot express today with interfaces and type switches: the compiler knows whether you handled every case.

The example the README gives looks like this:

go
enum Result {
    Ok(value: int),
    Error(message: string)
}

result := divide(10, 2)
match result {
    Ok(value) => fmt.Printf("Success: %d\n", value),
    Error(msg) => fmt.Printf("Error: %s\n", msg)
}

Safe navigation is a separate feature and the README shows it applied to struct fields, method calls and plain Go pointers in the same expression family. The examples include chained defaults, where several `??` fallbacks resolve in order down to a literal. Because these compile to Go, each `?.` becomes a nil check in the output. The ergonomic win is real, but the generated code is doing the same work you would have written, which is exactly the point the README makes about zero overhead.

The functional helpers follow the same pattern. The README shows map, filter and reduce called as methods on a slice, each taking a function literal. Those are not Go methods on slices, so they must be rewritten during transpilation. Whether the rewrite allocates a new slice per call is not stated in the README, and that is the kind of thing worth checking by running `dingo go` on examples/14_functional and reading the output.

Where Dingo is the wrong tool

The README does not document rollback. There is no section on converting a Dingo file back to Go, no migration guide, and no statement about what happens to a codebase that has mixed .dingo and .go files over time. If your team needs a documented exit path before adopting a pre-1.0 language, that gap is the deciding factor, not the feature list.

The second limitation is the version situation. The latest tagged release is v0.9.0 from 2026-01-08, while the README targets v1.0 in Q1 2026 and describes Phase 10 as complete. Those two facts sit awkwardly together: the phases are well past ten, the tags are not. Anyone planning around a stable release should read CHANGELOG.md and the releases page rather than the roadmap.

There is also a structural cost that the README does not address. Every developer on the team needs the dingo binary, and every editor needs the LSP integration to be working, or the experience degrades to writing files that a command line tool later rejects. The repository has an editors/ directory, so integration work exists, but the README does not enumerate which editors are supported or at what level. A team of one can absorb that. A team of twenty with mixed editor preferences cannot, without checking editors/ first.

Finally, the project is candid that it is a playground. That is fine for a side project or an internal tool. It is a poor fit for anything with a compliance review that asks what language the source is written in.

Dingo and Borgo: two answers to the same question

The README names Borgo directly as the prior art that proved transpiling to Go works, and credits it with roughly 4.5k stars. The two projects share the core idea but differ in emphasis. Borgo is presented as the proof of concept; Dingo positions itself as the version with better IDE integration, source maps and a pure Go implementation.

That last point is the substantive difference. A pure Go implementation means the compiler is built with the same toolchain as the code it produces, so a Go developer can read the compiler source, and the build step is `go build` rather than installing a separate language runtime. The LSP proxy and source maps are the second difference, and they target day-to-day editing rather than the language itself. If your interest is the type system, Borgo's design may be the more settled reference. If your interest is using this in an editor without fighting the tooling, Dingo is the one making that bet explicitly.

The README does not offer a feature-by-feature comparison, so treat the Borgo mention as a pointer to read, not as a benchmark.

Licence, maintenance and what upgrading costs

The repository's LICENSE file is Apache 2.0 according to the badge in the README, but the repository metadata reports the licence as NOASSERTION, meaning the automated classifier could not confirm a standard identifier. That mismatch is worth resolving with whoever handles licensing at your organisation before you vendor the compiler. There is also a NOTICE file in the root, which is standard Apache 2.0 practice and may carry attribution requirements. None of this is legal advice; read LICENSE and NOTICE yourself.

On maintenance, the last push to the default branch was on 2026-09-10, which is recent, and the repository is not archived. The release cadence visible in the tags is uneven: v0.5.0 and v0.6.0 landed a day apart in December 2025, v0.9.0 followed in January 2026, and no further tag appears in the release list. Active commits with infrequent tags is a normal pattern for a project that has not stabilised its API, and it means upgrading means tracking main rather than picking a version.

The upgrade cost follows from the transpiler model. Your .dingo files are the source of truth, and the generated .go files are build artefacts. If a new compiler version changes how a construct is lowered, the diff shows up in generated code, not in your source. That is easier to review than a hand-written refactor, but only if generated files are not committed alongside the source. The README does not say which convention it expects, and the repository has a .gitignore you can read for the answer.

Editorial conclusion

Dingo is for Go teams that want Result types, exhaustive match and safe navigation while keeping the compiled output as ordinary Go, and that can accept building the compiler from source. It is not for teams that need a documented rollback path or a stable v1.0, since the README targets v1.0 in Q1 2026 and the latest tagged release is v0.9.0 from 2026-01-08. Before committing, verify three things: that your Go toolchain satisfies the go.mod requirement of go 1.25.4, that dingo go on one real file produces Go your reviewers accept, and that the LSP proxy keeps gopls working in your editor.

Frequently asked questions

How do I install Dingo?

The README documents building from source: clone the repository, run `go build -o dingo ./cmd/dingo`, and optionally add the resulting binary directory to PATH. There is no published installer or package in the README.

How do I use Dingo on a Go file?

Create a file with the .dingo extension and run one of three subcommands: `dingo build` transpiles and compiles to a binary, `dingo run` transpiles and executes, and `dingo go` emits .go files without compiling. The README shows all three applied to hello.dingo.

Is Dingo a new runtime or a replacement for Go?

Neither. The README describes it as a language that compiles to clean, idiomatic Go, with zero runtime overhead and zero new dependencies. You keep the Go toolchain and the compiled output is a Go binary.

What Go version does Dingo need?

The README badge states Go 1.21+, but the repository's go.mod declares go 1.25.4. Check your installed toolchain against the module file before building, since a lower version is the likely cause of a failed build.

Does Dingo work with gopls?

The README states Phase 10 is complete with an LSP integration that includes a gopls proxy and auto-rebuild on save. The repository depends on go.lsp.dev/protocol and related packages for its language server.

Is Dingo stable enough for production?

The README calls the project a playground for Go's future and sets a v1.0 target of Q1 2026, while the latest tagged release is v0.9.0. The README also does not document a rollback or migration path back to plain Go.

Official sources

  1. Issues
  2. MadAppGang/dingo on GitHub
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/madappgang-dingo.svg)](https://hysenlabs.com/projects/madappgang-dingo)