← Back to Home

Rust & Go Enum Guide

Systems & Backend

Rust & Go Enum Complete Guide

Rust's enums are powerful algebraic data types that support carrying data and pattern matching. Go doesn't have native enums, but can achieve similar functionality with constants plus iota. This guide will help you use enums correctly in these two systems-level languages.

We'll explore Rust enum definitions, pattern matching, serde serialization, trait implementations, and best practices for simulating enums in Go using iota and custom types.

Rust Enums: The Power of Algebraic Data Types

Rust's enums are far more powerful than other languages—each variant can carry different types of data. Combined with match expressions, they elegantly handle various cases. This makes enums ideal tools for expressing complex states and business logic.

Typical Patterns

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub enum OrderStatus {
    Pending,
    Paid,
    Refunded { reason: String },
}

impl OrderStatus {
    pub fn is_terminal(&self) -> bool {
        matches!(self, OrderStatus::Refunded { .. })
    }
}

The derive macro automatically implements common traits for enums, while serde provides powerful serialization capabilities.

Simulating Enums in Go: Constants, iota, and Type Aliases

Go's design philosophy favors simplicity, so it doesn't provide enum types. But we can achieve similar effects using custom types plus constants, with iota enabling automatic constant incrementation.

iota Pattern

type OrderStatus int

const (
    OrderStatusPending OrderStatus = iota
    OrderStatusPaid
    OrderStatusRefunded
)

func (s OrderStatus) String() string {
    return [...]string{"pending", "paid", "refunded"}[s]
}

By implementing the String() method, enums can display friendly text in logs and error messages.

String Enum

type PaymentMethod string

const (
    PaymentMethodCard  PaymentMethod = "card"
    PaymentMethodPaypal PaymentMethod = "paypal"
)

func ParsePaymentMethod(v string) (PaymentMethod, error) {
    switch v {
    case string(PaymentMethodCard):
        return PaymentMethodCard, nil
    case string(PaymentMethodPaypal):
        return PaymentMethodPaypal, nil
    default:
        return "", fmt.Errorf("unknown payment method: %s", v)
    }
}

String-type enums are better suited for scenarios requiring persistence or API transmission.

Cross-Language Interoperability & Toolchain

In microservice architectures, Rust and Go often need to communicate via gRPC, GraphQL, or REST APIs. Unified enum definitions can avoid type conversion errors.

Serialization Matrix

  • ✔ ProtoBuf enum – Rust uses `prost`, Go uses `protoc-gen-go`.
  • ✔ GraphQL enum – Use `async-graphql` / `gqlgen`.
  • ✔ JSON Schema / OpenAPI – Unified string representation.

Testing Strategies

Rust can use snapshot tests to ensure serialization format remains unchanged, Go commonly uses table-driven approaches to test all enum values.

Comprehensive tests can promptly detect enum definition inconsistencies during refactoring.

Rust & Go Enum Toolkit

  • serde + enum attribute quick reference
  • Rust property-based tests (quickcheck) for enum validation
  • Go enum generation scripts (stringer, custom templates)
  • Interoperability guide: Rust ↔ Go gRPC enum mapping

FAQ

Common ways to serialize Rust enums?

Use `serde` derive, combine with `rename_all` to control fields, or use `serde_repr`/`num_enum` to bind integer values.

How to ensure each Rust enum branch implements a function?

Encapsulate behavior in `impl` using `match`, or leverage `enum_dispatch`/trait objects; the compiler will warn about uncovered branches.

How to print friendly strings for Go enums?

Implement the `String()` method or use the `stringer` tool to generate; and provide a `Parse` function to handle input.

Why doesn't Go have native enums?

Go's design philosophy favors simplicity, using constants + custom types is sufficient; the benefit is flexibility, the drawback is lack of compile-time constraints, requiring additional testing.