package main

import (
    "fmt"
    "reflect"
)

type People struct {
    Age   int
    Name string
}

type TestInterface interface {
    GetName() string
}

func (p *People) UpdateName(newName string) {
    p.Name = newName
}
func (p *People) GetName() string {
    return p.Name
}

func main() {
    u := People{18, "kuteng"}
    //返回指定对象的Kind类型
    fmt.Println(reflect.TypeOf(32).Kind())
    fmt.Println(reflect.ValueOf(32).Kind())

    //根据方法名找方法
    fmt.Println(reflect.TypeOf(&u).MethodByName("UpdateName"))
    fmt.Println(reflect.ValueOf(&u).MethodByName("UpdateName"))

    //返回第i个方法
    fmt.Println(reflect.TypeOf(&u).Method(0))
    fmt.Println(reflect.ValueOf(&u).Method(0))

    //返回拥有的方法总数,包括unexported方法
    fmt.Println(reflect.TypeOf(&u).NumMethod())
    fmt.Println(reflect.ValueOf(&u).NumMethod())

    //取struct结构的第n个field
    fmt.Println(reflect.TypeOf(u).Field(0))
    fmt.Println(reflect.ValueOf(u).Field(1))

    //嵌套的方式取struct的field,比如v.FieldByIndex(1,2,3)等价于 v.field(1).field(2).field(3)
    fmt.Println(reflect.TypeOf(u).FieldByIndex([]int{0}))
    fmt.Println(reflect.ValueOf(u).FieldByIndex([]int{0}))

    //返回名称匹配match函数的field
    fmt.Println(reflect.TypeOf(u).FieldByName("ID"))
    fmt.Println(reflect.ValueOf(u).FieldByName("Name"))

    //返回struct所包含的field数量
    fmt.Println(reflect.TypeOf(u).NumField())
    fmt.Println(reflect.ValueOf(u).NumField())

    //分配内存时的内存对齐字节数
    fmt.Println(reflect.TypeOf(u).Align())
    //作为struct的field时内存对齐字节数
    fmt.Println(reflect.TypeOf(u).FieldAlign())
    //type名 string类型
    fmt.Println(reflect.TypeOf(u).Name())
    //包路径, "encoding/base64", 内置类型返回empty string
    fmt.Println(reflect.TypeOf(u).PkgPath())
    //该类型变量占用字节数
    fmt.Println(reflect.TypeOf(u).Size())
    //type的string表示方式
    fmt.Println(reflect.TypeOf(u).String())
    //判断该类型是否实现了某个接口
    fmt.Println(reflect.TypeOf(u).Implements(reflect.TypeOf((*TestInterface)(nil)).Elem()))
    //判断该类型能否赋值给某个类型
    fmt.Println(reflect.TypeOf(u).AssignableTo(reflect.TypeOf(People{})))
    //判断该类型能否转换为另外一种类型
    fmt.Println(reflect.TypeOf(u).ConvertibleTo(reflect.TypeOf(1)))
    //判断该类型变量是否可以比较
    fmt.Println(reflect.TypeOf(u).Comparable())
    //取该类型的元素,指针指向的结构
    fmt.Println(reflect.TypeOf(&u).Elem())

    //调用函数
    fmt.Println(reflect.ValueOf(&u).MethodByName("GetName").Call([]reflect.Value{}))
    //判断能否取地址
    fmt.Println(reflect.ValueOf(&u).CanAddr())
    //判断Interface方法能否使用
    fmt.Println(reflect.ValueOf(&u).CanInterface())
    //判断值能否改变
    fmt.Println(reflect.ValueOf(&u).CanSet())

    a := []int{0, 1}
    //获取容量 Array/Chan/Slice
    fmt.Println(reflect.ValueOf(a).Cap())
    c := make(chan int)
    //关闭channel
    reflect.ValueOf(c).Close()
    //返回指针实际的值
    fmt.Println(reflect.ValueOf(&u).Elem())
    //索引操作 Array/Slice/String
    fmt.Println(reflect.ValueOf(a).Index(0))
    //修改数组第一个索引的值
    reflect.ValueOf(a).Index(0).Set(reflect.ValueOf(1))
    fmt.Println(a[0])
    //将当前value以interface形式返回
    fmt.Println(reflect.ValueOf(&u).Interface())
    //判断是否为nil,chan, func, interface, map, pointer, or slice valu
    fmt.Println(reflect.ValueOf(&u).IsNil())
    //是否是可操作的Value,返回false表示为zero Value
    fmt.Println(reflect.ValueOf(&u).IsValid())
    //获取长度,适用于Array, Chan, Map, Slice, or String
    fmt.Println(reflect.ValueOf(a).Len())
    m := map[int]string{1: "topgoer.com", 2: "topgoer.cn"}
    //对map类型按key取值
    fmt.Println(reflect.ValueOf(m).MapIndex(reflect.ValueOf(1)))
    //map类型的所有key的列表
    for index, key := range reflect.ValueOf(m).MapKeys() {
        fmt.Println("key=", key)
        fmt.Println("idnex=", index)
    }
    //返回value的Type
    fmt.Println(reflect.ValueOf(1).Type())
}