Strongly typed union type in golang with generics*.
- with exhaustive pattern matching support
- with json marshalling including generics
- and as a bonus, can generate compatible typescript types for end-to-end type safety in your application
Historically in languages without union types like golang, unions were solved either by using Visitor pattern, or using iota
and switch
statement, or other workarounds.
Visitor pattern requires a lot of boiler plate code and hand crafting of the Accept
method for each type in the union.
iota
and switch
statement is not type safe and can lead to runtime errors, especially when new type is added and not all case
statements are updated.
On top of that, any data marshalling like to/from JSON requires additional, hand crafted code, to make it work.
MkUnion solves all of those problems, by generating opinionated and strongly typed meaningful code for you.
package example
//go:generate mkunion
// union declaration
//go:tag mkunion:"Vehicle"
type (
Car struct {
Color string
Wheels int
}
Plane struct {
Color string
Engines int
}
Boat struct {
Color string
Propellers int
}
)
func CalculateFuelUsage(v Vehicle) int {
// example of pattern matching over Vehicle union type
return MatchVehicleR1(
v,
func(x *Car) int {
return x.Wheels * 2
},
func(x *Plane) int {
return x.Engines * 10
},
func(x *Boat) int {
return x.Propellers * 5
},
)
}
func ExampleToJSON() {
var vehicle Vehicle = &Car{
Color: "black",
Wheels: 4,
}
result, _ := shared.JSONMarshal(vehicle)
fmt.Println(string(result))
// Output: {"$type":"example.Car","example.Car":{"Color":"black","Wheels":4}}
}
func ExampleFromJSON() {
input := []byte(`{"$type":"example.Car","example.Car":{"Color":"black","Wheels":4}}`)
vehicle, _ := shared.JSONUnmarshal[Vehicle](input)
fmt.Printf("%#v", vehicle)
// Output: &example.Car{Color:"black", Wheels:4}
}
- Read getting started to learn more.