go语言通过反射创建结构体、赋值、并调用对应的操作

作者:jingxian 时间:2024-03-16 15:52:47 

我就废话不多说了,大家还是直接看代码吧~


package main
import (
"fmt"
"reflect"
"testing"
)
type Call struct {
Num1 int
Num2 int
}
func (call Call) GetSub(name string){
fmt.Printf("%v 完成了减法运算,%v - %v = %v \n", name, call.Num1, call.Num2, call.Num1 - call.Num2)
}
func (call *Call) GetSum(name string){
fmt.Printf("%v 完成了加法运算,%v + %v = %v \n", name, call.Num1, call.Num2, call.Num1 + call.Num2)
}
func TestReflect(t *testing.T) {
var (
call *Call
rValues []reflect.Value
rValues2 []reflect.Value
)
ptrType := reflect.TypeOf(call) //获取call的指针的reflect.Type
trueType := ptrType.Elem() //获取type的真实类型
ptrValue := reflect.New(trueType) //返回对象的指针对应的reflect.Value
call = ptrValue.Interface().(*Call)
trueValue := ptrValue.Elem() //获取真实的结构体类型
trueValue.FieldByName("Num1").SetInt(123)//设置对象属性,注意这个一定要是真实的结构类型的reflect.Value才能调用,指针类型reflect.Value的会报错
//ptrValue.FieldByName("Num2").SetInt(23)
trueValue.FieldByName("Num2").SetInt(23)
//rValues = make([]reflect.Value, 0)
rValues = append(rValues, reflect.ValueOf("xiaopeng"))//调用对应的方法
fmt.Println(rValues)
trueValue.MethodByName("GetSub").Call(rValues)
/*
fixme 在反射中,指针的方法不可以给实际类型调用,实际类型的方法可以给指针类型调用,因为go语言对这种操作做了封装
所以下面一句是没问题的
下下一句会运行时报错
*/
//ptrValue.MethodByName("GetSub").Call(rValues)
//trueValue.MethodByName("GetSum").Call(append(rValues2, reflect.ValueOf("hiram")))
ptrValue.MethodByName("GetSum").Call(append(rValues2, reflect.ValueOf("hiram")))
fmt.Println(call)
/*
fixme 在实际使用中  指针和实体都能相互转换,不会影响调用
但是指针的方法在方法体内的操作会影响到结构体本身属性
而实体的方法不会,因为go对于结构体、数组、基本类型都是值传递
*/
call.GetSub("aaa")
(*call).GetSub("bbb")
call.GetSum("ccc")
(*call).GetSum("ddd")
}

补充:golang 反射 reflect 设置 struct 字段

说明1 reflect.Value区分CanSet和Can not Set

所以, 必须要返回成Can set的reflect.Value

如:


s := reflect.ValueOf(&t).Elem()

然后就可以happy的设值了, 可是不能随便设值的, 一个通用的方法就是使用Set(v Value)方法,

说明2 将值转成reflect.Value类型

下面的这段代码就是转成Value类型


sliceValue := reflect.ValueOf([]int{1, 2, 3}) // 这里将slice转成reflect.Value类型

说明3 reflect.ValueOf 参数必须是一个 指针 或 interface Elem()才可以正常调用

func (Value) Elem func (v Value) Elem() Value

Elem returns the value that the interface v contains or that the pointer v points to. It panics if v's Kind is not Interface or Ptr. It returns the zero Value if v is nil.

Elem返回接口v包含的值或指针v指向的值。 如果v的Kind不是Interface或Ptr,它会感到恐慌。 如果v为零,它将返回零值。

实例代码

代码1:


func Destroy(subj interface{}) {
stype := reflect.ValueOf(subj).Elem()
field := stype.FieldByName("Status")
if field.IsValid() {
field.SetString("Destroyed")
}
}
func TestDestroy(t *testing.T) {
// Initialize data
jaeger := Jaeger{Name: "Cherno Alpha", Country: "RU", Status: "Active"}
kaiju := Kaiju{Alias: "Scissure", Origin: "Sydney", Status: "Unknown"}
shatterdome := Shatterdome{Location: "Lima"}
// Destroy everything
Destroy(&jaeger)
Destroy(&kaiju)
Destroy(&shatterdome)
// Check the result
if jaeger.Status != "Destroy" {
t.Error("jaeger was not destroyed")
}
if kaiju.Status != "Destroy" {
t.Error("kaiju was not destroyed")
}
}

代码2:


type T struct {
   Age int
   Name string
   Children []int
}
t := T{12, "someone-life", nil}
s := reflect.ValueOf(&t).Elem()
s.Field(0).SetInt(123) // 内置常用类型的设值方法
sliceValue := reflect.ValueOf([]int{1, 2, 3}) // 这里将slice转成reflect.Value类型
s.FieldByName("Children").Set(sliceValue)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持

来源:https://www.cnblogs.com/hirampeng/p/11204475.html

标签:go,反射,结构体,赋值
0
投稿

猜你喜欢

  • 为MySQL提权简单方法

    2009-08-29 15:21:00
  • Typora 0.11.18免费版本安装使用教程(亲测可用)

    2023-10-29 16:56:58
  • 利用pyshp包给shapefile文件添加字段的实例

    2023-08-12 15:48:38
  • spring boot 测试单元修改数据库不成功的解决

    2024-01-21 00:20:14
  • MySQL如何设置某个字段的值自增

    2024-01-27 09:49:09
  • go语言开发中如何优雅得关闭协程方法

    2024-02-15 00:12:55
  • python 删除excel表格重复行,数据预处理操作

    2023-04-19 06:10:33
  • Python使用scipy.fft进行大学经典的傅立叶变换

    2022-09-10 20:26:13
  • PDO::inTransaction讲解

    2023-06-06 08:32:27
  • python基础教程之实现石头剪刀布游戏示例

    2022-02-09 15:41:11
  • pytorch从头开始搭建UNet++的过程详解

    2023-03-11 09:19:24
  • Python光学仿真之对光的干涉理解学习

    2021-05-24 04:47:52
  • IE 下 href 的 BUG

    2008-11-10 12:32:00
  • sql查询点滴记录

    2012-01-05 19:07:49
  • javascript弹出窗口总结

    2009-08-21 12:40:00
  • MySQL索引类型一览 让MySQL高效运行起来

    2010-04-22 16:52:00
  • python 利用pandas将arff文件转csv文件的方法

    2021-05-31 05:49:34
  • Dreamweaver使用疑难解答

    2009-09-13 18:41:00
  • Java基于正则表达式实现的替换匹配文本功能【经典实例】

    2023-03-15 22:27:44
  • Asp中如何设计跨越域的Cookie

    2008-10-24 09:46:00
  • asp之家 网络编程 m.aspxhome.com