最近在實現golang,看到個go的特性語法: typeswitch guard。
typeswitch guard語法如下:
package main
import "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關鍵字而是類型。
如果類型正確那麼程序正常,如果類型錯誤則panic
func 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)