最近在实现golang,看到个go的特性语法: typeswitch guard。
typeswitch guard语法如下:
package mainimport "fmt"func typeChecking(p interface{}) { switch p.(type) { case int: fmt.Print("int") case float64: fmt.Printf("float64") }}func main(){ typeChecking(56.67) typeChecking(56)}
运行时判断p的类型,并根据是什么类型进行对应操作,较之与其他语言比如java的连续if else
在语法上要美观一些:
if(p instance of TypeA){ System.out.println("Type A");}else if (p instance of TypeB){ System.out.println("Type B");}...
另外需要注意它的参数只能是interface,因为其他类型都可以被编译器编译时type inference,只有interface具有运行时类型。
最后可以看到,类型区别语法和类型断言很像的,仅在于p.(X)括号内不是type关键字而是类型。
如果类型正确那么程序正常,如果类型错误则panicfunc typeAssertion(p interface{}){ q:=p.(int) fmt.Print(q)}func main(){ typeAssertion(5.7)}
上述例子如果p的类型是int,那么正常输出;如果不是则painc。
既然实现golang,就多说一点点
typeswitch 在golang 1.11对应的ast 结构如下:TypeSwitchGuard struct { Lhs *Name // nil means no Lhs := X Expr // X.(type) expr}
也就是说typeswitch guard其实是有两种语法的:
X.(type)Lhs := X.(type)
我们可以将typeswitch guard的值赋给一个变量,变量的值相当于p本身的值:
func typeChecking(p interface{}) { switch q :=p.(type) { case int: fmt.Print("int") case float64: fmt.Print(q) fmt.Printf("float64") }}func main(){ typeChecking(56.67)}
最后输出
56.67float64
前面说到它的语法和type assertion也非常类似,这是有原因的。编译器区分两者仅在于p.(X)括号内是否为关键字type
case _Lparen: p.next() if p.got(_Type) {//如果括号内是关键字type则是typeswitch,否则便是type assertion t := new(TypeSwitchGuard) // t.Lhs is filled in by parser.simpleStmt t.pos = pos t.X = x x = t } else { t := new(AssertExpr) t.pos = pos t.X = x t.Type = p.type_() x = t } p.want(_Rparen)