西城网站建设,学校网站设计流程,网站工商网监标,wordpress秀Go语言断言和类型查询
1、类型断言
类型断言(Type Assertion)是一个使用在接口值上的操作#xff0c;用于检查接口类型变量所持有的值是否实现了期望的接
口或者具体的类型。
在Go语言中类型断言的语法格式如下#xff1a;
// i.(TypeNname)
value, ok : x.(T)其中…Go语言断言和类型查询
1、类型断言
类型断言(Type Assertion)是一个使用在接口值上的操作用于检查接口类型变量所持有的值是否实现了期望的接
口或者具体的类型。
在Go语言中类型断言的语法格式如下
// i.(TypeNname)
value, ok : x.(T)其中x 表示一个接口的类型如果是具体类型变量则编译器会报non-interface type xxx on leftT 表
示一个具体的类型(也可为接口类型)。
该断言表达式会返回 x 的值也就是 value和一个布尔值也就是 ok可根据该布尔值判断 x 是否为 T 类
型 如果 T 是具体某个类型类型断言会检查 x 的动态类型是否等于具体类型 T。如果检查成功类型断言返回的 结果是 x 的动态值其类型是 T。 如果 T 是接口类型类型断言会检查 x 的动态类型是否满足 T。如果检查成功x 的动态值不会被提取返回 值是一个类型为 T 的接口值。 无论 T 是什么类型如果 x 是 nil 接口值类型断言都会失败。
示例代码如下
package mainimport (fmt
)func main() {var x interface{}x 10value, ok : x.(int)// 10,truefmt.Print(value, ,, ok)
}运行结果如下
# 程序结果
10,true需要注意如果不接收第二个参数也就是上面代码中的 ok断言失败时会直接造成一个 panic如果 x 为 nil 同样也
会 panic。
示例代码如下
package mainimport (fmt
)func main() {var x interface{}x Hellovalue : x.(int)fmt.Println(value)
}运行结果如下
# 输出结果
panic: interface conversion: interface {} is string, not int接口断言通常可以使用 comma,ok 语句来确定接口是否绑定某个实例类型或者判断接口绑定的实例类型是否实
现另一个接口。
re,ok : body.(io.ReadCloser)
if,ok : r.Body.(*maxBytesReader);2、类型查询
接口类型查询的语法格式如下
switch v : i.(type){case typel:XXXXcase type2:XXXXdefault:XXXX
}接口查询有两层语义一是查询一个接口变量底层绑定的底层变量的具体类型是什么二是查询接口变量绑定的底
层变量是否还实现了其他接口。
(1)、i 必须是接口类型
具体类型实例的类型是静态的在类型声明后就不再变化所以具体类型的变量不存在类型查询类型查询一定是
对一个接口变量进行操作。也就是说上文中的i必须是接口变量如果i是未初始化接口变量则v的值是 nil。
package mainimport (fmtio
)func main() {var i io.Reader//此处i是为未初始化的接口变量,所以v为nilswitch v : i.(type) {case nil://nilfmt.Printf(%T\n, v)default:fmt.Printf(default)}
}(2)、case 字句后面可以跟非接口类型名也可以跟接口类型名匹配是按照 case 子句的顺序进行的。 如果 case 后面是一个接口类型名且接口变量i绑定的实例类型实现了该接口类型的方法则匹配成v的类 型是接口类型v底层绑定的实例是i绑定具体类型实例的副本。 如果 case 后面是一个具体类型名且接口变量i绑定的实例类型和该具体类型相同则匹配成功此时v 就是 该具体类型变量v的值是i绑定的实例值的副本。 如果 case 后面跟着多个类型使用逗号分隔接口变量i绑定的实例类型只要和其中一个类型匹配则直接使 用o赋值给v相当于 v:o。这个语法有点奇怪按理说编译器不应该允许这种操作语言实现者可能想让 type switch 语句和普通的 switch 语句保持一样的语法规则允许发生这种情况。 如果所有的case字句都不满足则执行 default 语句此时执行的仍然是 v:o最终v的值是o。此时使用v没 有任何意义。 fallthrough 语句不能在 Type Switch 语句中使用。
package mainimport (fmtiologos
)func main() {var i io.Reader// 此处i是为未初始化的接口变量,所以v为nilswitch v : i.(type) {case nil:// nilfmt.Printf(%T\n, v)default:fmt.Printf(default)}f, err : os.OpenFile(notes.txt, os.O_RDWR|os.O_CREATE, 0755)if err ! nil {log.Fatal(err)}defer f.Close()i fswitch v : i.(type) {// i的绑定的实例是*osFile类型实现了io.ReadWriter接口所以下面case匹配成功case io.ReadWriter:// v是io.ReadWriter接口类型所以可以调用Write方法v.Write([]byte(io.ReadWriter\n))// Type Switch Result: io.ReadWriterfmt.Println(Type Switch Result: io.ReadWriter)// 由于上一个case已经匹配就算这个case也匹配也不会走到这里case *os.File:v.Write([]byte(*os.File\n))fmt.Println(Type Switch Result: *os.File)//这里可以调用具体类型方法v.Sync()default:fmt.Println(Type Switch Result: unknown)return}switch v : i.(type) {// 匹配成功v的类型就是具体类型*os.Filecase *os.File:v.Write([]byte(*os.File\n))// Type Switch Result: *os.Filefmt.Println(Type Switch Result: *os.File)v.Sync()//由于上一个case已经匹配就算这个case也匹配也不会走到这里case io.ReadWriter://v是io.ReadWriter接口类型所以可以调用Write方法v.Write([]byte(io.ReadWriter\n))fmt.Println(Type Switch Result: io.ReadWriter)default:fmt.Println(Type Switch Result: unknown)return}switch v : i.(type) {//多个类型f满足其中任何一个就算匹配case *os.File, io.ReadWriter:// 此时相当于执行力v : i ,v和i是等价的使用v没有意义。if v i {// truefmt.Println(true)}default:return}
}# 程序输出
nil
Type Switch Result: io.ReadWriter
Type Switch Result: *os.File
truepackage mainimport (fmt
)func main() {var a inta 10// the type of a is intgetType(a)
}func getType(a interface{}) {switch a.(type) {case int:fmt.Println(the type of a is int)case string:fmt.Println(the type of a is string)case float64:fmt.Println(the type of a is float)default:fmt.Println(unknown type)}
}# 程序输出
the type of a is int