Dingo
A meta-language for Go that adds Result types, error propagation (?), and pattern matching while maintaining 100% Go ecosystem compatibility
Install / Use
/learn @MadAppGang/DingoREADME
Dingo
<img src="docs/mascot.png" alt="Dingo mascot" width="200"/>Go that escaped.
Features • Quick Start • Examples • Status • Roadmap • Contributing
At a Glance
Sum Types: Working | Pattern Matching: Working | Error Propagation: Working | Tuples: Working | Safe Navigation: Working | Playground for Go's Future | v1.0 Target: Q1 2026
</div>Look, I love Go. But...
You know that feeling when you're writing Go and you type if err != nil for the 47th time in a single file?
Or when you forget to check for nil and your production server learns what a panic feels like?
Or when you're explaining to a Rust developer why Go doesn't have sum types and they look at you like you just said "we don't believe in seatbelts"?
Yeah. That's why Dingo exists.
What's Dingo?
Think TypeScript, but for Go.
Dingo is a language that compiles to clean, idiomatic Go code. Not some franken-runtime or a whole new ecosystem. Just better syntax that becomes regular Go.
The pitch: Write code with Result types, pattern matching, and null safety. Get back perfect Go code that your team can read, your tools can process, and your production servers can run at exactly the same speed.
Zero runtime overhead. Zero new dependencies. Zero "what's this weird thing in my transpiled code?"
Is this proven to work? Yes. Borgo (4.5k stars) already proved you can transpile to Go successfully. Dingo builds on that foundation with better IDE integration, source maps, and a pure Go implementation.
Why "Dingo"?
Ever wonder what a dingo actually is?
Thousands of years ago, they were domesticated dogs. Well-behaved. Following commands. Controlled.
Then they escaped to the Australian wild and evolved into something science couldn't categorize. Not quite dog. Not quite wolf. Ungovernable.
The Go Gopher? Created at Google. Lives by the rules. Does what it's told.
Dingo broke free.
Here's the beautiful part: dingos are still canines. They didn't reject their DNA—they just refused to be controlled. Same with our language.
Every Go feature still works. Go 1.24 adds something? You get it in Dingo. Day one. Disable all plugins? You're running pure Go.
You're not losing anything. You're gaining freedom without asking permission.
Want pattern matching? Enable it. Want sum types? Already working. Think you can do it better? Fork the plugin and prove it.
Your language. Your rules. No committee required.
See MANIFESTO.md for why this terrifies the establishment.
Quick Start
Note: Dingo is in active development. Phase 10 Complete - Full LSP integration with gopls proxy, auto-rebuild on save, and comprehensive IDE support.
Latest (2025-12-09): ✅ Tuples & Documentation Update - Tuple type support (Phase 8) complete with destructuring, multi-return functions, and Option/Result integration. Golden tests updated to use current API patterns (.MustSome(), .MustOk() methods). See CHANGELOG.md for details.
Installation
# Clone the repository
git clone https://github.com/MadAppGang/dingo.git
cd dingo
# Build the compiler
go build -o dingo ./cmd/dingo
# Add to PATH (optional)
export PATH=$PATH:$(pwd)
Your First Dingo Program
Create hello.dingo:
package main
import "fmt"
func main() {
message := "Hello from Dingo!"
fmt.Println(message)
}
Build and run:
# Transpile to Go and compile to binary (like go build)
dingo build hello.dingo
# Transpile and run immediately (like go run)
dingo run hello.dingo
# Transpile to Go only (generates .go files without compiling)
dingo go hello.dingo
Try Working Features Now
Sum Types with Pattern Matching:
enum Result {
Ok(value: int),
Error(message: string)
}
func divide(a: int, b: int) Result {
if b == 0 {
return Error("division by zero")
}
return Ok(a / b)
}
result := divide(10, 2)
match result {
Ok(value) => fmt.Printf("Success: %d\n", value),
Error(msg) => fmt.Printf("Error: %s\n", msg)
}
Safe Navigation and Null Coalescing (Phase 7 ✅):
// Property access with safe navigation
city := user?.address?.city?.name ?? "Unknown"
// Method calls with safe navigation
email := user?.getProfile()?.email ?? "noreply@example.com"
// Works with Go pointers too!
timeout := config?.database?.timeout ?? 30
// Chained defaults
theme := user?.theme ?? project?.theme ?? global?.theme ?? "light"
Functional Utilities:
numbers := []int{1, 2, 3, 4, 5}
doubled := numbers.map(func(x int) int { return x * 2 })
evens := numbers.filter(func(x int) bool { return x % 2 == 0 })
sum := numbers.reduce(0, func(acc int, x int) int { return acc + x })
See examples/ and docs/features/ for more working code.
Why Dingo?
<div align="center"> <table> <tr> <td width="50%" valign="top">The Go Pain Points
- 47
if err != nilblocks per file - Nil pointer panics in production
- No sum types after 15 years of requests
- Verbose error handling drowning business logic
- No null safety operators
- Boilerplate enums requiring manual type guards
The Dingo Solution
?operator propagates errors cleanlyOption<T>makes nil checks compile-time safeenumkeyword with full sum type support- Pattern matching with exhaustiveness checking
?.and??for safe navigation and null coalescing- Zero overhead - transpiles to clean Go
Key Insight: Dingo doesn't change Go. It transpiles to it. Your team gets modern ergonomics, your production gets pure Go performance.
</div>The Hidden Superpower: Use Dingo Selfishly, Help Go Evolve Naturally
Here's what makes Dingo special — you get two massive benefits simultaneously:
1. Revolutionize YOUR Codebase TODAY
This is why you'll actually use Dingo:
- ✅ 67% less error handling boilerplate —
?operator instead of 47if err != nilblocks - ✅ 78% code reduction with sum types — Rust-style enums that just work
- ✅ Zero nil pointer panics — Option types that the compiler enforces
- ✅ Pattern matching — Exhaustive, type-safe, impossible to mess up
- ✅ Same performance — Transpiles to clean Go, zero runtime overhead
Your code becomes cleaner, safer, and more maintainable. Immediately.
This is the selfish reason to use Dingo. And it's a damn good reason.
2. Shape Go's Future (As a Natural Side Effect)
Here's the beautiful part you get for free:
While you're using Dingo to make YOUR code better, you're automatically contributing to Go's evolution:
- 📊 Your metrics become data — "67% reduction in error handling code across 50 real projects"
- 🐛 Your bugs find edge cases — Real problems that theoretical debates miss
- ✨ Your usage validates ideas — Proof that features work in production
- 📚 Your code becomes examples — Concrete demonstrations for Go proposals
You don't have to think about this. It just happens.
The TypeScript Parallel (This Is EXACTLY What Happened)
Developers didn't adopt TypeScript to "help JavaScript evolve."
They adopted it because it made their codebases better.
- TypeScript added types → Developers used them → JavaScript saw it worked → JavaScript added types
- TypeScript added async/await → Millions used it → JavaScript saw the value → JavaScript adopted it
- TypeScript added optional chaining → Everyone loved it → JavaScript added it officially
Developers used TypeScript selfishly. JavaScript evolved as a natural consequence.
Same thing is happening with Dingo and Go:
- You use Dingo because it makes error handling less painful
- 50,000 other developers do the same thing
- Go team sees 2 years of production data showing it works
- Go proposal now has concrete evidence instead of theoretical debate
- Everyone wins
You're not doing charity work. You're writing better code. Helping Go evolve is just a happy side effect.
Why This Matters More Than You Think
For decades, programming language evolution has been broken:
❌ The old way: Community → Proposal → Years of debate → Maybe no → Frustration
✅ The Dingo way: Developers → Use features → Data emerges → Go team decides with evidence
This is how TypeScript revolutionized JavaScript. Not through proposals, but through proving ideas in production.
The Win-Win-Win Scenario
🎯 You win: Better code today, zero waiting 🎯 Go team wins: Real data for decisions, reduced risk 🎯 Go ecosystem wins: Faster evolution, battle-tested features
Example: Sum Types
Imagine if before Go Proposal #19412 (sum types - 996+ 👍 but rejected), there was:
- ✅ 50,000 developers using it for 2 years
- ✅ Concrete metrics: 78% code reduction
- ✅ Known edge cases documented
- ✅ Production validation across 5,000+ projects
The proposal would have been impossible to reject with that evidence.
That's what Dingo enables. Every feature you use contributes data that could reshape Go's future.
This Is Not Hypothetical — TypeScript Proved It Works
Here's what actually happened with TypeScript and JavaScript:
| Feature | TypeScript Added | Developers Us
