一、使用反射获取指针结构体与结构体的区别
package main

import (
	"fmt"
	"reflect"
)

type hello struct {

}
func main() {
	//指针结构体
	h := &hello{}
	refH := reflect.TypeOf(h)
	fmt.Println(refH.PkgPath())
	fmt.Println(refH.Kind())
	fmt.Println(refH.Name())
	fmt.Println(refH.String())
	//创建一个结构体
	refH = refH.Elem()
	//获取结构体名
	fmt.Println(refH.Name())
	//获取类别
	fmt.Println(refH.Kind())
}

二、使用反射获取结构里的字段名,属性,tag标签
package main

import (
	"fmt"
	"reflect"
)

type hello struct {
   Name string `json:"name"`
   Age int `json:"age"`
}
func main() {
	h := hello{
		Name: "小王",
		Age:  15,
	}
	retH := reflect.TypeOf(h)
	//获取结构体里的名称
	for i := 0; i < retH.NumField(); i++ {
		field := retH.Field(i)
		fmt.Println("结构体里的字段名",field.Name)
		fmt.Println("结构体里的字段属性:",field.Type)
		fmt.Println("结构体里面的字段的tag标签",field.Tag)
	}
	//提取tag标签里的信息
	name, bool := retH.FieldByName("Name")
	if bool {
		fmt.Println("tag标签的信息为",name.Tag.Get("json"))
	}
}

三、使用反射查找结构体的匿名字段
package main

import (
	"fmt"
	"reflect"
)

//定义一个结构体
type Jack struct {
	x int
	Name string
	float64
	bool
	tom *Jack
}
func main() {
	//值包装结构体
	v := reflect.ValueOf(Jack{tom: &Jack{}})
	//获取结构体字段数
	field := v.NumField()
	fmt.Println("结构体字段数为:",field)
	//根据索引访问字段
	value := v.Field(0)
	fmt.Println("索引为0的字段类型为",value.Type())
	//根据名字查找字段类型
	name := v.FieldByName("Name").Type()
	fmt.Println("根据名字查找类型为",name)
	//匿名字段查找
	index := v.FieldByIndex([]int{4, 3}).Type()
	fmt.Println("匿名字段的类型",index)
}