使用反射遍历结构体的字段,调用结构体的方法,获取结构体标签的值,并修改结构体字段的值

该代码示例展示了如何在Go中使用`reflect`包来操作struct,包括设置字段值、读取json标签、调用结构体方法,并通过传递参数执行方法。主要涉及结构体定义、方法绑定以及反射在实际编程中的应用。
package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string		`json:"name"`
	Age int			`json:"p_age"`
	Score float32
	Sex string
}

func (s Person) Print() {
	fmt.Println("----start----")
	fmt.Println(s)
	fmt.Println("----end----")
}

func (s Person) GetSum(n1, n2 int) int {
	return n1 + n2
}

func (s Person) 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.Elem().Kind()

	if kd != reflect.Struct {
		fmt.Println("expect struct")
		return
	}

	num := val.Elem().NumField()
	val.Elem().Field(0).SetString("Lilei")
	fmt.Printf("struct has %d fields\n", num)

	for i := 0; i< num; i++ {
		fmt.Printf("field %d: 值为=%v\n", i, val.Elem().Field(i))

		//获取到struct标签,注意需要使用reflect.Type获取tag标签的值
		tagVal := typ.Elem().Field(i).Tag.Get("json")
		if tagVal != "" {
			fmt.Printf("field %d: tag为=%v\n", i, tagVal)
		}
	}

	numOfMethod := val.Elem().NumMethod()
	fmt.Printf("struct has %d methods\n", numOfMethod)

	val.Elem().Method(1).Call(nil)

	var params []reflect.Value
	params = append(params, reflect.ValueOf(10))
	params = append(params, reflect.ValueOf(40))

	//传入的参数是[]reflect.Value
	res := val.Elem().Method(0).Call(params)
	//返回结果是[]reflect.Value
	fmt.Println("res=", res[0].Int())
}

func main() {
	var a = Person{
		Name:  "Demon",
		Age:   10,
		Score: 20,
		Sex:   "male",
	}

	TestStruct(&a)
	fmt.Println(a)
}

### Go 主结构体内嵌结构体方法访问外部结构体字段 在Go语言中,当一个结构体嵌入另一个结构体时,可以通过特定的方式让内嵌结构体方法访问其所属主结构体字段。这涉及到理解Go中的匿名字段以及方法接收者的作用范围。 #### 方法一:传递主结构体指针给内嵌结构体方法 为了实现这一点,可以在定义内嵌结构体方法时接受一个指向主结构体类型的参数。这样就可以直接操作或读取主结构体的数据成员。下面是一个具体的例子来展示这种做法: ```go package main import ( "fmt" ) type OuterStruct struct { Name string InnerObj InnerStruct } func (o *OuterStruct) Init(name string, hobby string) { o.Name = name o.InnerObj.Init(hobby, o) } type InnerStruct struct{} // 定义一个带有额外参数的方法用于获取外部结构体的信息 func (i *InnerStruct) PrintInfo(outer *OuterStruct) { fmt.Printf("Name from outer struct: %s\n", outer.Name) fmt.Printf("Hobby inside inner struct: %s\n", i.GetHobby()) } func (i *InnerStruct) GetHobby() string { return "默认爱好" // 这里只是一个示例,默认返回固定字符串 } func (i *InnerStruct) SetHobby(hobby string, outer *OuterStruct) { i.PrintInfo(outer) // 调用其他方法传入外部结构体实例 } ``` 在这个例子中,`PrintInfo` 和 `SetHobby` 方法都接受了来自外部结构体的一个指针作为参数,从而允许它们访问和修改外部结构体的内容[^1]。 #### 方法二:利用闭包捕获上下文环境变量 另一种方式是在初始化阶段创建闭包形式的方法,这些方法能够捕捉到当前作用域内的局部变量(即外部结构体)。不过这种方法相对复杂一些,不推荐初学者使用。 对于上述两种方案的选择取决于具体应用场景和个人偏好;通常情况下,第一种更为直观易懂且易于维护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值