1.类型断言
类型断言 提供了访问接口值底层具体值的方式。
t := i.(T)
该语句断言接口值 i 保存了具体类型 T,并将其底层类型为 T 的值赋予变量 t。
若 i 并未保存 T 类型的值,该语句就会触发一个panic。
为了 判断 一个接口值是否保存了一个特定的类型,类型断言可返回两个值:其底层值以及一个报告断言是否成功的布尔值。
t, ok := i.(T)
若 i 保存了一个 T,那么 t 将会是其底层值,而 ok 为 true。
否则,ok 将为 false 而 t 将为 T 类型的零值,程序并不会产生panic。
请注意这种语法和读取一个映射时的相同之处。
package main
import "fmt"
func main() {
var i interface{} = "hello"
s := i.(string)//i保存了string类型的值
fmt.Println(1,s)
f = i.(float64) // i未保存string类型值,报panic
fmt.Println(5,f)
s, ok := i.(string)//判断接口i是否保存了string类型的值
fmt.Println(2,s, ok)
var j interface{} =""
t, ok :=j.(string)//判断接口i是否保存了string类型的值
fmt.Println(3,t, ok)
f, ok := i.(float64)//i并未保存float64类型,所以f视为float类型的零值
fmt.Println(4,f, ok)
}
2.类型选择
类型选择 是一种按顺序从几个类型断言中选择分支的结构。
类型选择与一般的 switch 语句相似,不过类型选择中的 case 为类型(而非值), 它们针对给定接口值所存储的值的类型进行比较。
switch v := i.(type) {
case T:
// v 的类型为 T
case S:
// v 的类型为 S
default:
// 没有匹配,v 与 i 的类型相同
}
类型选择中的声明与类型断言 i.(T) 的语法相同,只是具体类型 T 被替换成了关键字 type。
此选择语句判断接口值 i 保存的值类型是 T 还是 S。在 T 或 S 的情况下,变量 v 会分别按 T 或 S 类型保存 i 拥有的值。在默认(即没有匹配)的情况下,变量 v 与 i 的接口类型和值相同。
package main
import "fmt"
func do(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("Twice %v is %v\n", v, v*2)
case string:
fmt.Printf("%q is %v bytes long\n", v, len(v))
default:
fmt.Printf("I don't know about type %T!\n", v)
}
}
func main() {
do(21)
do("hello")
do(true)
}
3.fmt.Stringer 接口
Stringer接口定义在fmt包中,该接口包含String()方法。任何类型只要定义了String()方法,进行Print输出时,就可以得到定制输出。
package main
import "fmt"
type IPAddr [4]byte
// TODO: 给 IPAddr 添加一个 "String() string" 方法
func (IP IPAddr) String() string{
return fmt.Sprintf("%v.%v.%v.%v",IP[0],IP[1],IP[2],IP[3])
}
func main() {
hosts := map[string]IPAddr{
"loopback": {127, 0, 0, 1},
"googleDNS": {8, 8, 8, 8},
}
for name, ip := range hosts {
fmt.Printf("%v: %v\n", name, ip)
}
}
4.使用error表示错误
使用 error 值来表示错误状态
package main
import (
"fmt"
)
type ErrNegativeSqrt float64
func (e ErrNegativeSqrt) Error() string{
return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e))
}
func Sqrt(x float64) (float64, error) {
z:=1.00
for i:=0;i<10;i++{
z =z - ((z*z - x)/ (2*z))
}
if x < 0{
return 0,ErrNegativeSqrt(x)
}
return z, nil
}
func main() {
fmt.Println(Sqrt(2))
fmt.Println(Sqrt(-2))
}
1.414213562373095 <nil>
0 cannot Sqrt negative number: -2