Go Tips ¶
Here lies my collection of random things I've learned how to do in Go.
Helpful Links ¶
Emulating Closed Sum-Type / Discriminated Unions using the AsAny
Pattern ¶
2025-05-04
OpenAI's Go library makes extensive use of this, and I quite like it.
The trick is to use a sealed-interface union wrapper. It's a struct with mutually-exclusive pointer fields plus an unexported marker interface. You don't use the wrapper directly; use constructors to instantiate new instances.
package main
import "fmt"
type Dog struct{}
func NewDog(d Dog) PetUnion {
return PetUnion{OfDog: &d}
}
func (Dog) bark() { fmt.Println("bark") }
type Cat struct{}
func NewCat(c Cat) PetUnion {
return PetUnion{OfCat: &c}
}
func (Cat) meow() { fmt.Println("meow") }
// keep this private
type anyPet interface {
implAnyPetUnion()
}
func (Dog) implAnyPetUnion() {}
func (Cat) implAnyPetUnion() {}
type PetUnion struct {
OfDog *Dog
OfCat *Cat
}
func (u PetUnion) AsAny() anyPet {
switch {
case u.OfDog != nil:
return u.OfDog
case u.OfCat != nil:
return u.OfCat
}
return nil
}
func Example() {
pet := NewDog(Dog{})
switch v := pet.AsAny().(type) {
case *Dog:
v.bark()
case *Cat:
v.meow()
}
// Output:
// bark
}
Recurring Tasks ¶
2025-04-28
package main
import "time"
func NewHourlyCron(f func()) {
ticker := time.NewTicker(time.Hour)
defer ticker.Stop()
for {
select {
case <-ticker.C:
f()
}
}
}
Format Time in Kitchen Time ¶
2025-04-28
package main
import (
"fmt"
"time"
)
func Example() {
fmt.Println(time.Now().Format(time.Kitchen))
// Output:
// 11:00PM
}
Capitalize Words ¶
2025-04-28
package main
import (
"fmt"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
func Capitalize(s string) string {
return cases.Title(language.English).String(s)
}
func ExampleCapitalize() {
fmt.Println(Capitalize("abcdef"))
fmt.Println(Capitalize("hi there"))
fmt.Println(Capitalize("CAPITALIZED"))
// Output:
// Abcdef
// Hi There
// Capitalized
}