Marvin Preuss
1d4ae27878
All checks were successful
continuous-integration/drone/push Build is passing
2.0 KiB
2.0 KiB
astcast
Package astcast wraps type assertion operations in such way that you don't have to worry about nil pointer results anymore.
Installation
go get -v github.com/go-toolsmith/astcast
Example
package main
import (
"fmt"
"github.com/go-toolsmith/astcast"
"github.com/go-toolsmith/strparse"
)
func main() {
x := strparse.Expr(`(foo * bar) + 1`)
// x type is ast.Expr, we want to access bar operand
// that is a RHS of the LHS of the addition.
// Note that addition LHS (X field) is has parenthesis,
// so we have to remove them too.
add := astcast.ToBinaryExpr(x)
mul := astcast.ToBinaryExpr(astcast.ToParenExpr(add.X).X)
bar := astcast.ToIdent(mul.Y)
fmt.Printf("%T %s\n", bar, bar.Name) // => *ast.Ident bar
// If argument has different dynamic type,
// non-nil sentinel object of requested type is returned.
// Those sentinel objects are exported so if you need
// to know whether it was a nil interface value of
// failed type assertion, you can compare returned
// object with such a sentinel.
y := astcast.ToCallExpr(strparse.Expr(`x`))
if y == astcast.NilCallExpr {
fmt.Println("it is a sentinel, type assertion failed")
}
}
Without astcast
, you would have to do a lots of type assertions:
package main
import (
"fmt"
"github.com/go-toolsmith/strparse"
)
func main() {
x := strparse.Expr(`(foo * bar) + 1`)
add, ok := x.(*ast.BinaryExpr)
if !ok || add == nil {
return
}
additionLHS, ok := add.X.(*ast.ParenExpr)
if !ok || additionLHS == nil {
return
}
mul, ok := additionLHS.X.(*ast.BinaryExpr)
if !ok || mul == nil {
return
}
bar, ok := mul.Y.(*ast.Ident)
if !ok || bar == nil {
return
}
fmt.Printf("%T %s\n", bar, bar.Name)
}