golang 基础——反射

Posted 猎人在吃肉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 基础——反射相关的知识,希望对你有一定的参考价值。

文章目录

1、反射普通变量

package main

import (
	"fmt"
	"reflect"
)


func test01() 
	var v float64 = 1.2

	// 方法1
	vo := reflect.ValueOf(v)
	fmt.Printf("Type=%T , Kind=%v ,val = %v\\n", vo, vo.Kind(), vo.Float())

	// 方法2
	vo2 := vo.Interface()
	v2 := vo2.(float64)
	上面两行代码可以合并一行,如下
	//v2 :=  vo.Interface().(float64)
	

	fmt.Println("v2 =", v2)


// 使用反射修改变量 str的值
func test02() 
	var str string = "tom"
	fs := reflect.ValueOf(&str)
	fs.Elem().SetString("jack")
	fmt.Printf("str = %v\\n", str)


type Student struct 
	Name string
	Age  int


func test03(b interface) 

	fs := reflect.ValueOf(b)
	itV := fs.Elem().Interface()
	stu2 := itV.(Student)

	fmt.Printf("stu2 name = %v\\n", stu2.Name)
	//name2 := stu2.Name

	fs.Elem().FieldByName("Name").SetString("jack")
	//fs2 := reflect.ValueOf(&name2)
	//fs2.Elem().SetString("jack")

	//fmt.Printf("stu2 name = %v\\n", stu2.Name)


func main() 
	stu := Student
		Name: "zhangsan",
		Age:  30,
	
	test03(&stu)
	fmt.Printf("main() stu2 name = %v\\n", stu.Name)

2、反射结构体

package main

import (
	"fmt"
	"reflect"
)

type Monster struct 
	Name  string `json:"name"`
	Age   int    `json:"monster_name"`
	Score float32
	Sex   string


func (s Monster) Print() 
	fmt.Println("-----start--------")
	fmt.Println(s)
	fmt.Println("-----end--------")

func (s Monster) GetSum(n1, n2 int) int 
	return n1 + n2

func (s Monster) Set(name string, age int, score float32, sex string) 
	s.Name = name
	s.Age = age
	s.Score = score
	s.Sex = sex


func TestStruct(a interface) 
	typ := reflect.TypeOf(a)
	val := reflect.ValueOf(a)
	kd := val.Kind()
	if kd != reflect.Struct 
		fmt.Println("expect struct")
		return
	

	num := val.NumField()
	fmt.Printf("struct has %d fields\\n", num)
	for i := 0; i < num; i++ 
		fmt.Printf("Field %d 值: %v \\n", i, val.Field(i))
		// 获取结构体的tag标签的值
		tagVal := typ.Field(i).Tag.Get("json")
		if tagVal != "" 
			fmt.Printf("Field %d tag: %v\\n", i, tagVal)
		
	
	numOfMethod := val.NumMethod()
	fmt.Printf("struct has %d methods\\n", numOfMethod)

	// 调用第2个方法,注意,方法是按照ASCI排序的
	val.Method(1).Call(nil)

	// 调用第1个方法。先准备参数的值
	var params []reflect.Value
	params = append(params, reflect.ValueOf(10))
	params = append(params, reflect.ValueOf(40))
	// 调用第1个方法,并传入参数
	res := val.Method(0).Call(params)
	// 返回结果是[]reflect.Value
	fmt.Println("res =", res[0].Int())


func main() 
	var aa = Monster
		Name:  "黄鼠狼精",
		Age:   400,
		Score: 60.5,
	
	TestStruct(aa)

运行命令:

go run .\\main.go

运行结果如下

struct has 4 fields
Field 0 值: 黄鼠狼精
Field 0 tag: name
Field 1 值: 400
Field 1 tag: monster_name
Field 2 值: 60.5
Field 3 值:
struct has 3 methods
-----start--------
黄鼠狼精 400 60.5 
-----end--------
res = 50

3、对反射结构体进行测试

package main

import (
	"reflect"
	"testing"
)

type User struct 
	UserId string
	Name   string


func TestReflectStructPtr(t *testing.T) 
	var (
		model *User
		st    reflect.Type
		elem  reflect.Value
	)
	st = reflect.TypeOf(model) // 获取*User
	t.Log("reflect.TypeOf =", st.Kind().String())
	st = st.Elem() // st指向User
	t.Log("reflect.TypeOf.Elem = ", st.Kind().String())
	elem = reflect.New(st)

	t.Log("reflect.New = ", elem.Kind().String())
	t.Log("reflect.New.Elem =", elem.Elem().Kind().String())
	model = elem.Interface().(*User)
	elem = elem.Elem()
	elem.FieldByName("UserId").SetString("654321")
	elem.FieldByName("Name").SetString("jack")
	t.Log("model model.Name", model, model.Name)

运行命令:

go test -v

运行结果:

=== RUN   TestReflectStructPtr
    user_test.go:20: reflect.TypeOf = ptr
    user_test.go:22: reflect.TypeOf.Elem =  struct
    user_test.go:25: reflect.New =  ptr
    user_test.go:26: reflect.New.Elem = struct
    user_test.go:31: model model.Name &654321 jack jack
--- PASS: TestReflectStructPtr (0.00s)
PASS
ok      go_code/project02/demo03/zuoye01        0.022s

以上是关于golang 基础——反射的主要内容,如果未能解决你的问题,请参考以下文章

Golang基础_10-反射reflection

golang基础--reflect反射

golang 反射

golang反射自定义tag

动物:黄鼬黄鼠狼

golang/go语言Go语言之反射