PONYλM2Modula-2
CodeCompared
for Go programmers

You already know Go.Now explore other languages.

Side-by-side, interactive cheatsheets for Go programmers
comparing Go to other languages. Every example runs live in your browser — no setup, no installation.

▶ Start with RubyBrowse comparisons ↓Explore the language map ↗

Choose your own path by reordering languages

Ruby⚡ Works Offline⚡ Offline

Where Go programmers go when they want expressiveness over explicitness. Ruby trades Go's ceremony — error checks after every call, explicit loops, no generics-free verbosity — for blocks, exceptions, and an object model so consistent that even integers have methods.

  • Blocks and Enumerable — map, select, reduce built into every collection, replacing Go's hand-written for-range loops
  • Exceptions instead of error values — the happy path is never interrupted by if err != nil; errors propagate until something rescues them
  • Dynamic typing and duck typing — no type declarations, no interface satisfaction to declare; if an object responds to the method, it works
  • Open classes and metaprogramming — reopen String or Integer and add methods at runtime; define methods on the fly
  • Pattern matching — case/in destructures arrays and hashes and binds variables in one step, with no manual index checks
JavaScriptAlpha⚡ Works Offline⚡ Offline

Ten thousand goroutines become one event loop. There is no go statement, no channel, no mutex and no -race — one thread, where blocking it stops everything. In exchange the data race cannot happen. Then: exceptions instead of if err != nil, two empties instead of nil, one f64 instead of the sized-integer family, and objects that never copy.

  • No goroutines and no parallelism: Promise.all is the shape a WaitGroup becomes, and only I/O actually overlaps
  • Blocking the one thread stops the page or the server — a request handler that computes is a production incident
  • Channels become async generators (one producer, one consumer), select becomes Promise.race without cancellation, and a worker pool is fifteen lines you write
  • No mutex, no atomics, no memory model — run-to-completion semantics mean total++ cannot interleave; the races that remain are logical, across await points
  • Errors are thrown, not returned, and nothing warns about an unhandled one — plus the rejection that vanishes when nobody attaches a handler in the same tick
  • Both languages are structurally typed, which no other Go pairing gets to say — Go checks at compile time, JavaScript at the moment of the call
  • One number type: int64 arrives as a rounded double through JSON.parse, so send 64-bit identifiers as strings
  • A struct copies and an object never does; and GOOS=js GOARCH=wasm gets a section of its own, including why esbuild ships as a binary instead
PythonBeta⚡ Works Offline⚡ Offline

Where Go programmers go for data, scripting, and getting an idea running in five lines. Python trades Go's static types and compile step for dynamic typing, exceptions, comprehensions, and a vast library ecosystem — the lingua franca of data science and machine learning.

  • Dynamic and duck typing — no type declarations and no interface to satisfy; if an object has the method, it works
  • Comprehensions — [x*x for x in items if ...] replaces the hand-written map/filter loops Go makes you spell out
  • Exceptions with try/except/finally instead of (value, error) and the endless if err != nil
  • Classes, inheritance, and dunder methods (__add__, __repr__) — real OOP and operator overloading, which Go has none of
  • Generators, decorators, and an enormous standard library plus PyPI — batteries included for data and ML
CPre-Alpha

The language Go was built by C people to replace, and still has to talk to. Most of what Go gives you is a small struct plus a discipline, and C makes you supply both by hand — which is exactly what reading a header for cgo requires.

  • A slice IS { pointer, length, capacity } — writing that struct out explains len, cap, why append must be reassigned, and why two slices can share one array
  • A Go string carries a length and may contain a zero byte; a C string ends at the first one — the difference C.CString exists to bridge, allocating a copy you must C.free
  • defer is the goto cleanup idiom, in reverse order, on every exit path, maintained for you
  • An interface value is two pointers — the data and a table of functions — which is why a nil interface and an interface holding a nil pointer are different things
  • C has the one feature Go removed on purpose: pointer arithmetic. Its absence is precisely why Go can have a collector that moves objects and fixes pointers up
DartPre-Alpha

From structs and goroutines to classes and Futures. Dart brings full OOP, sound null safety, named parameters, and async-first design to a Go programmer who already thinks in types.

  • Sound null safety — String is non-nullable at compile time; String? makes it nullable. No nil panics at runtime
  • Named parameters with required — replaces the fragile positional argument lists that Go forces on every API
  • Full OOP: classes, inheritance, mixins, and abstract interfaces — where Go uses structs + embedding + implicit interfaces
  • Exceptions instead of (value, error) returns — Dart propagates errors automatically; no if err != nil at every call site
  • Futures and Streams replace goroutines and channels for async I/O; Isolates provide true parallelism with no shared memory
  • Dart 3 Records give multiple return values, and sealed classes with exhaustive switch expressions add pattern matching
RustPre-Alpha

Go's systems niche without the garbage collector — and with a type system that catches far more at compile time. Rust trades goroutines and GC for ownership, sum-type enums, and Result/Option, eliminating nil-panics and data races before the program ever runs.

  • Ownership and borrowing instead of a garbage collector — deterministic cleanup, no GC pauses, and data races caught at compile time
  • Enums are true sum types — what Go fakes with iota constants or tagged structs, with exhaustive match the compiler enforces
  • Result and Option replace (value, error) and nil — the ? operator collapses if err != nil, and there is no null to dereference
  • Traits with generics and bounds — like interfaces, but implemented explicitly, monomorphised, and able to carry default methods
  • Iterator pipelines — map/filter/fold as zero-cost abstractions, replacing Go's hand-written loops
TypeScriptAlpha⚡ Works Offline⚡ Offline

The same structural typing you already trust, with the type-level expressiveness Go leaves on the table. TypeScript interfaces are satisfied by shape — exactly like Go's — but the type system adds unions, literal types, and discriminated unions for the sum types Go never grew.

  • Structural interfaces, just like Go — a value fits an interface by its shape, not by declaring implements
  • Union types (number | string) and literal types ("active" | "inactive") express what Go can only fake with any and a type switch
  • Discriminated unions give exhaustively-checked sum types — the compiler flags the variant you forgot to handle
  • Errors are thrown and caught with try/catch, not returned as (value, error) — no if err != nil after every call
  • async/await over a single event loop replaces goroutines and channels — concurrency without the shared-memory races
ZigPre-Alpha

The systems language for Go programmers who want to drop the garbage collector. Zig keeps Go's small, readable spirit but makes memory explicit, errors part of the type system, and code generation happen at compile time — no runtime, no GC pauses, no hidden allocations.

  • Explicit allocators instead of a garbage collector — deterministic cleanup with defer/errdefer and no GC pauses
  • comptime — run real code at compile time, and write generics as ordinary functions taking a type parameter
  • Error unions (!T) with try/catch replace (value, error) and the endless if err != nil
  • Optionals (?T) instead of nil — absence is in the type, and there is no null pointer to dereference
  • Tagged unions with exhaustive switch give the sum types Go lacks; no hidden allocations or control flow anywhere
JavaPre-Alpha

The class-based, exception-driven system Go deliberately avoided. Java trades Go's implicit interfaces for an explicit implements keyword, its (value, error) returns for a full exception hierarchy, and its composition-only model for real inheritance — while sharing garbage collection and, since virtual threads, a genuinely lightweight concurrency story.

  • Explicit implements declarations instead of Go's implicit, structural interfaces — the single biggest philosophical gap between the two languages
  • Exceptions (try/catch/throws, checked vs. unchecked) instead of Go's explicit (value, error) return convention checked at every call site
  • Classes with extends inheritance instead of Go's struct embedding — a Java subclass genuinely is-a its parent, where Go composition only borrows fields and methods
  • Virtual threads (Java 21+) close much of the gap with goroutines — cheap, JVM-scheduled threads where a plain Thread used to be comparatively expensive
  • Older, more elaborate generics (wildcards, type erasure) versus Go's newer, simpler type-parameter generics introduced in 1.18
  • Garbage collection in both — one of the few places a Go programmer will feel immediately at home
OdinPre-Alpha

Go's readability without the garbage collector. Odin keeps defer, multiple return values, and zero-value initialization, then hands you the allocator — and adds the tagged unions and parametric procedures Go still makes you work around.

  • An implicit context carries the allocator — unlike Go's context.Context you never thread it through signatures, and reassigning context.allocator redirects every allocation below that point
  • Tagged union types with an exhaustive switch give the sum types Go lacks — no more interface{} plus a type switch that silently misses a case
  • Parametric polymorphism with $T is resolved at compile time and can take values, not just types: proc(array: [$N]$T) matches on the array length
  • or_return collapses the if err != nil { return err } block into a single suffix, and or_else supplies a fallback inline
  • No goroutines or channels — core:thread and core:sync give you OS threads and explicit synchronization, with no scheduler in the binary
  • #soa converts an array of structs into a struct of arrays while keeping items[index].field syntax — a data-layout change Go cannot express
Drag cards to reorder · your order is saved locally