golang 基础——反射

本文详细介绍了Go语言中的反射机制,包括反射普通变量、结构体以及对结构体的测试。通过示例展示了如何使用`reflect`包来获取变量的类型、值,以及如何修改结构体字段的值。此外,还演示了如何读取结构体字段的tag标签并调用结构体的方法。
摘要由CSDN通过智能技术生成

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值