七、golang中接口、反射
一、接口定义
1、定义
interface类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量
package main import ( "fmt" ) type test interface{ print() } type Student struct{ name string age int score int } func (p *Student)print(){ fmt.Println("name",p.name) fmt.Println("age",p.age) fmt.Println("score",p.score) } func main(){ var t test //创建接口对象 var stu Student=Student{ //实例化结构体 name:"stu1", age:20, score:100, } t=&stu //把实例化传给这个接口对象 t.print() //接口对象来调用接口的方法 } name stu1 age 20 score 100 上面的test就是一种类型
多态:
一种食物的多种形态,都可以按照统一的接口进行操作
上面的t可以指向Stu,也可以指向其他类型,这个就是多态
定义:
比如:
type example interface{
method1(参数列表) 返回值列表
method2(参数列表) 返回值列表
}
interface类型默认是一个指针
接口实现:
a、golang中的接口,不需要显示的实现,只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口
b、如果一个变量含有多个interface类型的方法,那么这个变量就实现了多个接口
c、要实现变量中接口的所有方法,才是实现了这个接口
接口嵌套:
一个接口可以嵌套在另外的接口,如下所示
type ReadWrite interface{
Read(b Buffer) bool
Write(b Buffer)bool
}
type Lock interface{
Lock()
Unlock()
}
type File interface{
ReadWrite
Lock
Close()
}
类型断言
类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型,可以采用以下方法进行转换
var t int var t int
var x interface{} var x interface {}
x=t x=t
y=x.(int)//转成int y ,ok=x.(int) //转成int,带检查
二叉排序树
时间复杂度和二分查找时间复杂度是一样的
为什么要使用接口?
接口是一个规范,不需要关注类等的实现。即,数据本来在mysql里面然后突然变成pg里面,只要接口不变,使用方就不需要更改
如果接口里面没有任何方法,那么我们就叫这个接口为空接口
package main import ( "fmt" ) type Carer interface{ GetName() string Run() DIDI() } func main(){ var car Carer fmt.Println(car) //<nil> } 上面打印出这个接口的值为nil
下面具体接口的用法:
package main
import (
"fmt"
)
type Carer interface{
GetName() string //这里前面定义的方法,后面代表返回值类型
Run()
DIDI()
}
type BWM struct{
Name string
}
func (p *BWM)GetName() string{
return p.Name
}
func (p *BWM)Run(){
fmt.Printf("%s is
Running",p.Name)
}
func (p *BWM)DIDI(){
fmt.Printf("%s is
didi",p.Name)
}
func main(){
var car Carer
fmt.Println(car) //<nil>
bwm:=BWM{
Name:"bwm",
}
car=&bwm
car.Run()
}
接口操作小结:
1、定义接口和方法,注意返回值
2、定义类型
3、定义类型实现的接口的方法,注意这里要实现接口所有的方法
4、声明定义的类型,声明接口变量的类型并且初始化,并把定义的类型赋值给接口变量的类型,注意指针
5、用定义的接口变量执行接口方法
鸭子类型
只要实现了接口相关的协议,那么这个就是接口
如sort只需要实现下面的接口就可以
func Sort(data Interface) 这里只需要传入接口就可以了
这个接口实现下面的方法
type Interface interface{
Len() int 长度
Less(I,j int) bool 比较两个数
Swap(I,j int) 交换两个数
}
注意下面的大小写
package main import ( "fmt" "math/rand" "sort" ) type Student struct{ Name string Id string Age int } type StudentArray []Student //定义这个是切片结构体 func (p StudentArray) Len() int { return len(p) } func (p StudentArray)Less(i,j int)bool{ return p[i].Name>p[j].Name //从大到小 } func (p StudentArray)Swap(i,j int){ p[i],p[j]=p[j],p[i] } func main() { var stus StudentArray for i := 0; i < 10; i++ { stu := Student{ Name: fmt.Sprintf("stu%d", rand.Intn(100)), Id: fmt.Sprintf("110%d", rand.Int()), Age: rand.Intn(100), } stus = append(stus, stu) } for _, v := range stus { fmt.Println(v) } //空行 fmt.Println("\n\n") //由于这里实现了sort的接口,所以这里可以直接调用 sort.Sort(stus) for _, v := range stus { fmt.Println(v) } }
反射
反射,可以在运行时动态获取变量的相关信息
import (“reflect”)
两个函数
a)reflect.TypeOf,获取变量的类型,返回reflect.Type类型
b)reflect.ValueOf 获取变来那个的值,返回reflect.Value类型
c) reflect.Value.Kind 获取变量的类别,返回一个变量
d) reflect.value.Interface() 转换成interface类型
a和c的区别:
类型和类别的区别
类别范围》类型
package main import( "fmt" "reflect" ) type Student struct{ Name string Age int Score float32 } func test(b interface {}){ t:=reflect.TypeOf(b) fmt.Println(t) //main.Student 类型 v:=reflect.ValueOf(b) k:=v.Kind() fmt.Println(k) //struct类别 iv:=v.Interface() stu,ok:=iv.(Student) if ok{ fmt.Printf("%v %T\n",stu,stu)//{stu01 18 92} main.Student } } func main(){ var a Student=Student{ Name:"stu01", Age:18, Score:92, } test(a) } 可以在动态运行时的时候的到b的很多信息,这就是反射 上面是三种转换 下main是获取值 package main import( "fmt" "reflect" ) type Student struct{ Name string Age int Score float32 } func test(b interface {}){ t:=reflect.TypeOf(b) fmt.Println(t) //main.Student 类型 v:=reflect.ValueOf(b) k:=v.Kind() fmt.Println(k) //struct类别 iv:=v.Interface() stu,ok:=iv.(Student) if ok{ fmt.Printf("%v %T\n",stu,stu)//{stu01 18 92} main.Student } } func testInt(b interface{}){ val :=reflect.ValueOf(b) c:=val.Int() //获取值 fmt.Printf("get value interface{} %d",c)//get value interface{} 1234 } func main(){ var a Student=Student{ Name:"stu01", Age:18, Score:92, } test(a) testInt(1234) } 小结: 1、反射获取具体的了类型 2、转化为具体的值 3、.Int()等获取具体的值 4、才能打印输出值