淘先锋技术网

首页 1 2 3 4 5 6 7

Golang反射reflect机制用法

请添加图片描述
请添加图片描述
重点:

  1. 转换的时候,如果转换的类型不完全符合,则直接panic,类型要求非常严格!
  2. 转换的时候,要区分是指针还是指
  3. 也就是说反射可以将“反射类型对象”再重新转换为“接口类型变量”
package main

import (
	"fmt"
	"reflect"
)

type Bookss struct {
	auth string
}

type User struct {
	Id   int
	Name string
	Age  int
}

func (this User) CallMethod() {
	fmt.Println("user is called ...")
	fmt.Printf("%v \n", this)
}

func DoFiledAndMethod(input interface{}) {
	// 获取input的type
	inputType := reflect.TypeOf(input)
	fmt.Println("inputType is :", inputType.Name())
	// 获取input的value
	inputValue := reflect.ValueOf(input)
	fmt.Println("inputValue is :", inputValue)
	// 通过type 获取里面的字段
	// 1.获取interface的reflect.Type,通过Type得到NumField,进行遍历
	// 2.得到每个field的数据类型
	// 3.通过filed有一个Interface()方法得到对应的value
	for i := 0; i < inputType.NumField(); i++ {
		filed := inputType.Field(i)
		value := inputValue.Field(i).Interface()
		fmt.Printf("%s: %v = %v \n", filed.Name, filed.Type, value)
	}
	// 通过type 获取里面的方法,调用它
	//1. 先获取interface的reflect.Type,然后通过NumMethod进行遍历
	//2. 再分别通过reflect.Type的Method获取对应的真实的方法(函数)
	//3. 最后对结果取其Name和Type得知具体的方法名
	//4. 也就是说反射可以将“反射类型对象”再重新转换为“接口类型变量”
	//5. struct 或者 struct 的嵌套都是一样的判断处理方式
	for i := 0; i < inputType.NumMethod(); i++ {
		m := inputType.Method(i)
		fmt.Printf("%s: %v \n", m.Name, m.Type)
	}
}

func main() {
	// ================================================================================
	//var s = []int{1, 2}

	//xx := reflect.ValueOf(s)
	//fmt.Println(xx)

	//yy := reflect.TypeOf(s)
	//fmt.Println(yy)

	// ================================================================================
	//book := Bookss{"张三"}
	//
	//xx := reflect.ValueOf(book)
	//fmt.Println(xx)
	//
	//yy := reflect.TypeOf(book)
	//fmt.Println(yy)

	// ================================================================================
	//num := false
	//fmt.Println(reflect.TypeOf(num))
	//fmt.Println(reflect.ValueOf(num))

	// ================================================================================

	//user := User{1, "张三", 30}
	//DoFiledAndMethod(user)

	// ================================================================================
	var num float64 = 1.2345

	pointer := reflect.ValueOf(&num)
	value := reflect.ValueOf(num)

	// 可以理解为“强制转换”,但是需要注意的时候,转换的时候,如果转换的类型不完全符合,则直接panic
	// Golang 对类型要求非常严格,类型一定要完全符合
	// 如下两个,一个是*float64,一个是float64,如果弄混,则会panic
	convertPointer := pointer.Interface().(*float64)
	convertValue := value.Interface().(float64)

	fmt.Println(convertPointer)
	fmt.Println(convertValue)
}

通过反射调用方法

  1. 要通过反射来调用起对应的方法,必须要先通过reflect.ValueOf(interface)来获取到reflect.Value,得到“反射类型对象”后才能做下一步处理
  2. reflect.Value.MethodByName这.MethodByName,需要指定准确真实的方法名字,如果错误将直接panic,MethodByName返回一个函数值对应的reflect.Value方法的名字。
  3. []reflect.Value,这个是最终需要调用的方法的参数,可以没有或者一个或者多个,根据实际参数来定。
  4. reflect.Value的 Call 这个方法,这个方法将最终调用真实的方法,参数务必保持一致,如果reflect.Value’Kind不是一个方法,那么将直接panic。
  5. 本来可以用u.ReflectCallFuncXXX直接调用的,但是如果要通过反射,那么首先要将方法注册,也就是MethodByName,然后通过反射调用methodValue.Call
package main

import (
	"fmt"
	"reflect"
)

type Users struct {
	Id   int
	Name string
	Age  int
}

// 有参数的方法
func (u Users) ReflectCallFuncHasArgs(name string, age int) {
	fmt.Println("ReflectCallFuncHasArgs name: ", name, ", age:", age, "and origal User.Name:", u.Name)
}

// 没有参数的方法
func (u Users) ReflectCallFuncNoArgs() {
	fmt.Println("ReflectCallFuncNoArgs")
}

// 如何通过反射来进行方法的调用?
// 本来可以用u.ReflectCallFuncXXX直接调用的,但是如果要通过反射,那么首先要将方法注册,也就是MethodByName,然后通过反射调动mv.Call

func main() {
	user := Users{1, "Allen.Wu", 25}

	// 1. 要通过反射来调用起对应的方法,必须要先通过reflect.ValueOf(interface)来获取到reflect.Value,得到“反射类型对象”后才能做下一步处理
	getValue := reflect.ValueOf(user)

	// 一定要指定参数为正确的方法名
	// 2. 先看看带有参数的调用方法
	methodValue := getValue.MethodByName("ReflectCallFuncHasArgs")
	args := []reflect.Value{reflect.ValueOf("wudebao"), reflect.ValueOf(30)}
	methodValue.Call(args)

	// 一定要指定参数为正确的方法名
	// 3. 再看看无参数的调用方法
	methodValue = getValue.MethodByName("ReflectCallFuncNoArgs")
	args = make([]reflect.Value, 0)
	methodValue.Call(args)
}

Golang反射解析结构体标签Tag

请添加图片描述

package main

import (
	"fmt"
	"reflect"
)

type resume struct {
	Name string `info:"name" doc:"我的名字"`
	Sex  string `info:"sex" doc:"我的性别"`
}

func findTag(str interface{}) {
	t := reflect.TypeOf(str).Elem()
	for i := 0; i < t.NumField(); i++ {
		tagInfo := t.Field(i).Tag.Get("info")
		tagDoc := t.Field(i).Tag.Get("doc")
		fmt.Println("info:", tagInfo, "tagDoc:", tagDoc)
	}
}
func main() {
	re := resume{}
	findTag(&re)
}

Golang结构体标签在json中的应用

package main

import (
	"fmt"
	"reflect"
)

type resume struct {
	Name string `info:"name" doc:"我的名字"`
	Sex  string `info:"sex" doc:"我的性别"`
}

func findTag(str interface{}) {
	t := reflect.TypeOf(str).Elem()
	for i := 0; i < t.NumField(); i++ {
		tagInfo := t.Field(i).Tag.Get("info")
		tagDoc := t.Field(i).Tag.Get("doc")
		fmt.Println("info:", tagInfo, "tagDoc:", tagDoc)
	}
}
func main() {
	re := resume{}
	findTag(&re)
}

结构体标签的应用

1.json编码、解码
2.orm映射关系