七、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、才能打印输出值

  

 

posted @ 2017-12-23 20:14  pi-pi-miao-miao  阅读(873)  评论(0编辑  收藏  举报