Go语言接口和反射

Posted parallel-y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)

  

  

以上是关于Go语言接口和反射的主要内容,如果未能解决你的问题,请参考以下文章

Go语言之反射

Go语言的反射机制

Go语言(十五) 反射

Go语言之Go语言反射

Go Web编程实战----反射

Go Web编程实战----反射