接口类型是对其它类型行为的抽象和归纳;由于接口类型不会和特定的实现细节绑定在一块儿,经过这种抽象的方式咱们可让咱们的函数更加灵活和更具备适应能力。函数
不少面向对象的语言都有类似的接口概念,但Go语言中接口类型的独特之处在于它是知足隐式实现的。也就是说,咱们没有必要对于给定的具体类型定义全部知足的接口类型;简单地拥有一些必需的方法就足够了。这种设计可让你建立一个新的接口类型知足已经存在的具体类型却不会去改变这些类型的定义;当咱们使用的类型来自于不受咱们控制的包时这种设计尤为有用。设计
接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。接口类型是一种抽象的类型。它不会暴露出它所表明的对象的内部值的结构和这个对象支持的基础操做的集合;它们只会展现出它们本身的方法。也就是说当你有看到一个接口类型的值时,你不知道它是什么,惟一知道的就是能够经过它的方法来作什么。指针
package main import "fmt" type canSay interface{ Say() } type dog struct { name string } type cat struct { name string } func (d dog) Say() { fmt.Println(d.name,"say") } func main() { var tom2 canSay tom := dog{name: "汤姆"} tom2 = tom tom2.Say() // 汤姆 say mi := cat{name: "猫咪"} tom2 = mi // 报错 由于cat没有实现接口规定的say方法 }
接口值,由两个部分组成,一个具体的类型和那个类型的值。它们被称为接口的动态类型和动态值。在咱们的概念模型中,一些提供每一个类型信息的值被称为类型描述符,好比类型的名称和方法。在一个接口值中,类型部分表明与之相关类型的描述符。code
package main import ( "bytes" "fmt" "io" "os" ) func main() { var w io.Writer fmt.Printf("类型:%T,值:%v\n",w,w) // 类型:<nil>,值:<nil> w = os.Stdout fmt.Printf("类型:%T,值:%v\n",w,w) // 类型:*os.File,值:&{0xc00007e280} w = new(bytes.Buffer) fmt.Printf("类型:%T,值:%v\n",w,w) // 类型:*bytes.Buffer,值: w = nil fmt.Printf("类型:%T,值:%v\n",w,w) // 类型:<nil> 类型:<nil> }
一个包含nil指针的接口不是nil接口对象
类型断言是一个使用在接口值上的操做。语法上它看起来像x.(T)被称为断言类型,这里x表示一个接口的类型和T表示一个类型。一个类型断言检查它操做对象的动态类型是否和断言的类型匹配。接口
x.(T)
T表示类型string
package main import ( "bytes" "fmt" "io" "os" ) func main() { var w io.Writer w = os.Stdout f := w.(*os.File) fmt.Printf("类型%T,值:%v\n",f,f) // 类型*os.File,值:&{0xc00014a280} c := w.(*bytes.Buffer) fmt.Printf("类型%T,值:%v\n",c,c) // panic }
判断是什么类型:it
package main import ( "fmt" ) func judgeType(x interface{}) { switch v := x.(type) { case string: fmt.Printf("is string:%v\n", v) case int: fmt.Printf("is int:%v\n", v) case bool: fmt.Printf("is bool:%v\n", v) default: fmt.Println("donot know ") } } func main() { judgeType(1) // is int:1 judgeType(true) // is bool:true judgeType("true") // is string:true judgeType(1.22) // donot know }
空接口是没有定义任何方法的接口。所以任何类型都实现了空接口。空接口类型的变量能够存储任意类型的变量。io
package main import "fmt" func main() { var test interface{} t1 := 1 test = t1 fmt.Printf("类型:%T 值:%v\n",test,test) // 类型:int 值:1 t2 := "zhaohaiyu" test = t2 fmt.Printf("类型:%T 值:%v\n",test,test) // 类型:string 值:zhaohaiyu t3 := false test = t3 fmt.Printf("类型:%T 值:%v\n",test,test) // 类型:bool 值:false t4 := 3.14 test = t4 fmt.Printf("类型:%T 值:%v\n",test,test) // 类型:float64 值:3.14 }
func show(test interface{}) { fmt.Printf("类型:%T 值:%v\n",test,test) }
var studentInfo = make(map[string]interface{}) studentInfo["name"] = "赵海宇" studentInfo["age"] = 18 fmt.Println(studentInfo) // map[age:18 name:赵海宇]