注意为什么建议用 *Vertec
package mainimport ("fmt""math")type Abser interface {Abs() float64}func main() {var a Abserf := MyFloat(-3.1415926)v := Vertex{3, 4}// 直接把定义的接口赋给相应的变量就OKa = ffmt.Println(a.Abs())a = &vfmt.Println(a.Abs())fmt.Println(v)}type MyFloat float64func (f MyFloat) Abs() float64 {if f < 0 {return float64(-f)}return float64(f)}type Vertex struct {X, Y float64}//Abs 为啥接收者是Vertex还是*Vertex都不影响呢// 但是对于其是v自身是有影响的,如果是*Vertex这里的v值就改变了// 如果只是Vertex的话,这里的v值不变// 不过这两种只能选择一种func (v Vertex) Abs() float64 {v.X = v.X + 2v.Y = v.Y + 8return math.Sqrt(v.X*v.X + v.Y*v.Y)}
两种不同的接口赋值
package mainimport "fmt"type Phone interface {call()}type Nokia struct{}type iPhone struct{}func (nokia Nokia) call() {fmt.Println("我是Nokia")}func (iphone iPhone) call() {fmt.Println("我是iPhone")}func main() {var phone Phone//这里用的是直接newphone = new(Nokia)phone.call()//这里用定义出一个变量,然后再把值赋给它的方式var iphone iPhonephone = iphonephone.call()}
类型里定义的变量接口方法里要用
package mainimport "fmt"type I interface {M()}type T struct {S string}func (t T) M() {fmt.Println(t.S)}func main() {//实例化的时候就得赋值了var i I = T{"test"}i.M()}
接口值
即是 接口也是值,也可传递,其值为(value,type)
即使 接口值的value是nil,方法也会被nil接收者调用 即保存了nil具体值的接口自身并不是nil
var i I var t T i = t describle(i) //输出 (
, main.T)
但是 nil 接口值既不保存具体值也不保存具体类型 ,调用方法会报错
package mainimport ("fmt""math")type I interface {M()}type T struct {S string}func (t *T) M() {fmt.Println(t.S)}type F float64func (f F) M() {fmt.Println(f)}func describle(i I) {fmt.Printf("(%v,%T)\n", i, i)}func main() {var i I//注意这里是怎么赋值的i = &T{"Hello"}describle(i) //(&{Hello},*main.T)i.M() //Helloi = F(math.Pi) //(3.141592653589793,main.F)describle(i) //3.141592653589793i.M()}
空接口
可以保存任意类型的值,因为任何类型都至少实现了零个方法
空接口常用来被处理未知类型的值,比如接收任意数量的参数
package mainimport "fmt"func main() {//空接口var A interface{}describle(A) //<nil>,<nil>var a intdescrible(a) //0,intvar s stringdescrible(s) //,string}//注意这个参数声明func describle(i interface{}) {fmt.Printf("%v,%T\n", i, i)}
类型断言
用 t := i.(T)
该语句断言接口值 i 保存了具体类型 T,并将其底层类型为 T 的值赋予变量 t
如果该 T 并不是i 的底层类型,那么将会产生一个panic
t, ok := i.(T)
同映射类似,如果是的返回OK,t是其底层值
如果不是,返回false ,t 的值是此处T 的零值
类型选择
switch结构来访问
package mainimport "fmt"func doType(i interface{}) {switch t := i.(type) {case int:fmt.Printf("value is %v\n", t)case string:fmt.Printf("%q is %v bytes long\n", t, len(t))default:fmt.Printf("type is %T", t)}}func main() {doType(21)doType("hello")doType(true)}
