Skip to content

Instantly share code, notes, and snippets.

@disintegrator
Last active March 1, 2024 13:04
Show Gist options
  • Save disintegrator/7bb58d80c584124e6bf66022c7b817af to your computer and use it in GitHub Desktop.
Save disintegrator/7bb58d80c584124e6bf66022c7b817af to your computer and use it in GitHub Desktop.
Assertions in Go
package main
import (
"errors"
"fmt"
"runtime"
)
func Assert(group string, pairs ...any) error {
if len(pairs)%2 != 0 {
return errors.New("assertions must be passed as pairs of string and boolean")
}
var errs error
_, file, no, ok := runtime.Caller(1)
caller := "<unknown>:0"
if ok {
caller = fmt.Sprintf("%s:%d", file, no)
}
for i := 0; i < len(pairs); i += 2 {
id, pred := pairs[i].(string), pairs[i+1].(bool)
if !pred {
errs = errors.Join(errs, &AssertionError{Invariant: id, Group: group, Caller: caller})
}
}
return errs
}
func MustAssert(group string, pairs ...any) {
if err := Assert(group, pairs...); err != nil {
panic(err)
}
}
type AssertionError struct {
Invariant string
Group string
Caller string
}
func (ae *AssertionError) Error() string {
return fmt.Sprintf("%s: assertion failed: %s: %s", ae.Caller, ae.Group, ae.Invariant)
}
package main
func doSomething(x int, species string, data []byte) {
MustAssert(
"do-something-inputs",
"non-zero-operand", x != 0,
"species-is-cat", species == "cat",
"non-empty-data", len(data) > 0,
)
// Do something with arguments
}
func main() {
doSomething(0, "dog", nil)
}
panic: /tmp/sandbox1646294625/assert.go:32: assertion failed: do-something-inputs: non-zero-operand
/tmp/sandbox1646294625/assert.go:32: assertion failed: do-something-inputs: species-is-cat
/tmp/sandbox1646294625/assert.go:32: assertion failed: do-something-inputs: non-empty-data
goroutine 1 [running]:
main.MustAssert(...)
/tmp/sandbox1646294625/assert.go:33
main.doSomething(0x60?, {0x49ab61?, 0xc000076058?}, {0x0?, 0x522268?, 0xc0000061c0?})
/tmp/sandbox1646294625/main.go:4 +0x139
main.main()
/tmp/sandbox1646294625/main.go:15 +0x29
Program exited.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment