第四章 Go语言接口和反射

一、接口

  定义

  接口定义了一个对象的行为规范,制定以规范并不实现,具体的对象需要实现规范的细节

//接口定义
type 接口名 interface {    //定义一个接口
    Talk()
    Eat() int    //返回int型
    Run()
}

  接口的实现

  一个对象只要包含接口中的方法,那么就是实现了这个接口,接口类型的变量可以保存具体类型的实例

type Animal interface{
    Talk()
    Eat()
    Name() string
}
type Dog struct{
}
func (d Dog) Talk(){
    fmt.Println("汪汪")
}
func (d Dog) Eat(){
    fmt.Println("吃骨头")
}
func (d Dog) Name() string{
    fmt.Println("旺财")
    return "旺财"
}
func test(){
    var b Dog
    var a Animal
    a = b
    a.Name()
    a,Eat()
    a.Talk()
}

  接口调用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 test(){
    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.Intn()),
            Age : randIntn(100),
        }
        stus = append(stus,stu)
    }
    for _,v := range stus{
        fmt.Println(v)
    }
    fmt.Println("\n\n")
    sort.Sort(stus)
    for _,v := range stus{
        fmt.Println(v)
    }
}

  空接口

  空接口没有定义任何方法,所以任何类型都能实现空接口

func test(){
    var a interface{}
    var b int = 100
    a = b
    fmt.Printlf(%T %v\n",a,a)    //int 100
    var c string = "hi"
    a = c
    fmt.Printf("%T %v\n",a,a)    //string hi
    var d map[string]int = make(map[string]int,10)
    d["abc"] = 100
    d["aaa"] = 30
    a = d
    fmt.Printf("%T %v\n",a,a)    //map[string]int map[abc:100 aaa:30]
}

func Descrtribe(a interface{}){
    fmt.Printf("type = %T %v\n",a,a)
}
type Student struct{
    Name string
    Sex int
}
func test2(){
    a := 99
    describe(a)    //type=int 99
    b := "hello"
    describe(b)    //type = string hello
    var stu Student = Student{
        Name:"user01",
        Sex:1,
    }
    describe(stu)    //type = main.Student {user01 1}
}

  类型断言

  获取接口类型里面存储的具体值

//OK语句判断
func describe(a interface{}) {
    s,ok := a.(int)
    if ok {    //使用ok语法,防止传入类型错误报错
        fmt.Println(s)
        return
    }
    str,ok := a.(string)
    if ok{
        fmt.Println(str)
        return
    }
    f,ok := a.(float32)
    if ok {
        fmt.Println(f)
        return
    }
    fmt.Println("输入错误")
    return
}
func test(){
    var a int = 100
    describe(a)
    var b string = "hi"
    describe(b)
}

//sitch-type语句判断
func testSwitch(a interface{}) {
    switch v := a.(type) {
    case stirng:L
        fmt.Printf("a is string,value:%v\n",v)
    case int:
        fmt.Printf("a is int,value:%v\n", v)
    case float32:
        fmt.Printf("a is float32,value:%v\n", v)
    default:
        fmt.Println("not support type\n")
    }
}
func test2(){
    var a int = 100
    testSwitch(a)
    var b string = "Parallel"
    testSAwitch(b)
}

  指针接收和值接收区别

  值类型实现的接口指针类型变量可以存入,指针类型实现的接口值类型变量不能存入

//同一兑现够可以实现多个接口
type Animal interface{
    Talk()
}
type Bu interface{
    Bu()
}
type Dog struct{
}
func (d Dog) Talk(){
    fmt.Println("汪汪")
}
func (d Dog) Bu(){
    fmt.Println(*狗是哺乳动物")
}
func test(){
    var d Dog
    var a Animal
    a = d
    a.Talk()
    var b Bu
    b = d  
    b.Bu()
}

  接口实现链表

type LinkNode struct{
    data interface{}
    next *LinkNode
}
type Link struct {
    head *LinkNode
    tail *LikNode
}
func (p *Link) InsertHead(data interface{}) {
    node := &LinkNode{
        data : data,
        next : nil,
    }
    if p.taiil == nil && p.head == nil{
        p.tail = node
        p.head = node
        return
    }
    node.next = p.head
    p.head = node
}
func (p *Link) InsertTail(data interfdace{}) {
    node := &LinkNode{
        data : data,
        next : nil,
    }
    if p.tail == nil && p.head{
        p.tail = node
        p.head = node
        reutrn
    }
    p.tail.next = node
    p.tail = node
}
func (p *Link) Trans(){
    q := p.head
    if q != nil {
        fmt.Println(q.data)
        q = q.next
    }
}
func main(){
    var intLink Link
    for i := 0;i<10;i++{
        intLink.InsertHead(i)
        intLink.InsertTail(i)
    }
    intLink.Trans()
}

  接口嵌套

type Animal interface {
    Eat()
}
type Describle interface {
    Describled()
}
type AdvanceAnimal interface {
    Animal
    Describle
}
type Dog struct {
}
func (d Dog) Eat() {
    fmt.Println("狗吃屎")
}
func (d Dog) Describled() {
    fmt.Println("狗")
}
func test() {
    var d Dog
    var a AdvanceAnimal
    a = d
    a.Eat()
    a.Describled()
}

  

二、反射

  定义

  空接口可以存储任何类型的变量,在运行时动态的获取一个变量的类型信息和值信息就是反射

//获取类型信息:reflect.TypeOf
import {
    "fmt"
    "reflect"
}
func reflect_example(a interface{}) {
    t := reflect.TypeOf(a)
    fmt.Printf("type of a is:%v\n",t)
}
func test(){
    var x float32 = 3.4
    reflect_example(x)
}

//获取变量的类型:Type.Kind()
import (
    "fmt"
    "reflect"
}
func reflect_example(a interface{}) {
    t := reflect.TypeOf(a)
    fmt.Printf("type of a is :%v\n",t)
    k := t.Kind()
    switch k {
    case reflect.Int64:
        fmt.Println("a is int64")
    case reflect.String:
        fmt.Printf("a is string")
    }
}
func test() {
    var x float32 = 3.4
    reflect_example(x)
}

//获取值信息:reflect.ValueOf
func reflect_value(a interface{}) {
    v := reflect.ValueOf(a)
    k := v.Kind()
    switch k {
    case reflect.Int64:
        fmt.Printf("a is int64,value is :%d",v.int())
    case reflect.Float64:
        fmt.Printf("a is Float64,value is:%f",v.Float())
    }
}
func test() {
    var x float64 = 3.4
    reflect_value(x)
}

//反射设置变量值:value.Elem().SetFloat()
func reflect_set_value(a interface{}) {
    v := reflect.ValueOf(a)
    k := v.Kind()
    switch k {
    case reflect.Int64:
        v.SetInt(100)
        fmt.Printf("a is int64,value is :%d",v.Int())
    case reflect.Float64:
        v.SetFloat(6.8)
        fmt.Printf("a is Float64,value is:%f",v.Float())
    case reflect.Ptr:
        fmt.Printf("set a to 6.8\n")
        qv.Elem().SetFloat(6.8)    //Elem()相当于指针赋值中的*
    }
}
func test() {
    var x float64 =  3.4
    reflect_set_valur(&x)
    fmt.Printf("x value is %v\n",x)
}
/*
注:
    var *p int = new(int)
    *p = 100    //正常指针赋值,设置的值需要和变量类型匹配
*/

  结构体反射

  获取和设置结构体字段的信息

//获取结构体信息
type Student struct {
    Name string
    Sex int
    Age int
}
func test(){
    var s Student
    v := reflect.ValueOf(s)
    t := v.Type()
    kind := t.Kind()
    switch kind {
    case reflect.Int64:
        fmt.Printf("s is int64\n")
    case reflect.Float32:
        fmt.Println("s is Float32\n")
    case reflect.Struct:
        fmt.Printf("s is struct\n")
        fmt.Printf("field num of s is %d\n",v.NumField())    //获取结构体的参数个数用NumField()
        for i:= 0;i<v.NumField();i++ {
            field := v.Field(i)
            fmt.Printf("name:%s type:%v value:%v\n",t.Field(i).Name,field.Type(),field.Interface())
        }
    default:
        fmt.Println("default")
    }
}

//设置结构体相关字段的值
type Student struct {
    Name stirng
    Sex int
    Age int
}
func test(){
    var s Student
    v := reflect.ValueOf(&s)
    v.Elem().Field(0).SetString("stu01")
    v.Elem().FieldByName("Sex").SetInt(2)
    v.Elem().FieldByName("Age").SetInt(15)
    fmt.Printf("s:%#v\n",s)
}

  获取和调用结构体方法中的信息

//获取结构体的方法信息
type Student struct {
    Name string
    Sex int
    Age int
    Score float32
}
func (s *Student) SetName(name string) {
    s.Name = name
}
func (s *Student) Print(){
    fmt.printf("%#v\n",s)
{
func test(){
    var s Student
    s.SetName("xxx")
    v := reflect.ValueOf(&s)
    t := v.Type()
    fmt.Printf("struct student have %d methods\n",t.NumMethod())
    for i := 0;i<NumMethod();i++ {
        method := t.Method(i)
        fmt.Printf("struct %d method,name:%s type :%v\n",i,method.Name,method.Type)
    }
}

//调用结构体中的方法
type Student struct {
    Name string
    Sex int
    Age int
    Score float 32
}
func (s *Student) SetName(name string) {
    s.Name = name
}
func (s *Student) Print() {
    fmt.Printf("%#v\n",s)
}
func test2() {
    var s Student
    s.SetName("xxx")
    v := reflect.ValueOf(&s)
    m1 := v.MethodByName("Print")
    var args []reflect.Value
    m1.Call(args)
//调用有参数结构体的方法
    m2 := v.MethodByName("SetName")
    var args2 []reflect.Value
    name := "stu01"
    nameVal := reflect.ValueOf(name)
    args2 = append(args2,nameVal)
    m2.Call(args2)
    m1.Call(args)
}

  

  

猜你喜欢

转载自www.cnblogs.com/parallel-Y/p/11420757.html