注意为什么建议用 *Vertec
package main
import (
"fmt"
"math"
)
type Abser interface {
Abs() float64
}
func main() {
var a Abser
f := MyFloat(-3.1415926)
v := Vertex{3, 4}
// 直接把定义的接口赋给相应的变量就OK
a = f
fmt.Println(a.Abs())
a = &v
fmt.Println(a.Abs())
fmt.Println(v)
}
type MyFloat float64
func (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 + 2
v.Y = v.Y + 8
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
两种不同的接口赋值
package main
import "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
//这里用的是直接new
phone = new(Nokia)
phone.call()
//这里用定义出一个变量,然后再把值赋给它的方式
var iphone iPhone
phone = iphone
phone.call()
}
类型里定义的变量接口方法里要用
package main
import "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 main
import (
"fmt"
"math"
)
type I interface {
M()
}
type T struct {
S string
}
func (t *T) M() {
fmt.Println(t.S)
}
type F float64
func (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() //Hello
i = F(math.Pi) //(3.141592653589793,main.F)
describle(i) //3.141592653589793
i.M()
}
空接口
可以保存任意类型的值,因为任何类型都至少实现了零个方法
空接口常用来被处理未知类型的值,比如接收任意数量的参数
package main
import "fmt"
func main() {
//空接口
var A interface{}
describle(A) //<nil>,<nil>
var a int
describle(a) //0,int
var s string
describle(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 main
import "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)
}