Type Definitions

The closest thing Go has to a union type or enum is a type definition combined with constants.

Pattern: String-based Enums

By creating a custom type based on a string, you can define a set of “allowed” values.

type status string

const (
    statusDelivered status = "delivered"
    statusBounced   status = "bounced"
    statusOpened    status = "opened"
)

func handleStatus(s status) { ... }

Type Safety Limitations

While this pattern is common and helpful, it is not perfectly safe:

  1. Literal Bypass: You can still pass a raw string literal to the function if the underlying types match: handleStatus("invalid") will compile.
  2. Explicit Conversion: A developer can convert any string into your custom type: handleStatus(status("random string")).

Despite these limitations, using custom types is strongly encouraged because it documents the intent of your code and helps prevent accidental errors when passing raw variables.