go语言通过反射创建结构体、赋值、并调用对应的操作
作者:jingxian 发布时间:2024-03-16 15:52:47
标签:go,反射,结构体,赋值
我就废话不多说了,大家还是直接看代码吧~
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
0
投稿
猜你喜欢
- 学了这么长时间的Pygame,一直想写个游戏实战一下。看起来很简单的游戏,写其来怎么这么难。最初想写个俄罗斯方块,想了很长时间如何实现,想来
- 前言:数据库非常重要,程序的数据增删改查需要数据库支持。python处理数据库非常简单。而且不同类型的数据库处理逻辑方式大同小异。本文以sq
- 1.Null数据的处理 1)检索出null值  
- 1.用一个栈【python中可以用List】就可以解决,时间和空间复杂度都是O(n)# -*- coding: utf8 -*-# 符号表S
- 一、_func 单下划线开头 --口头私有变量1.1、在模块中使用单下划线开头在Python中,通过单下划线_来实现模块级别的私有化,变量除
- 知道如何快速在命令行或者python脚本中实例化一个浏览器通常是非常有用的。每次我需要做任何关于web的自动任务时,我都使用这段python
- Dreamweaver从出道以来,其简便易用而又功能强大的“行为”(Behavior)一直是大家所关注的热点之一。在Dreamweaver
- 文字的多行处理在dom元素中很好办。但是canvas中没有提供方法,只有通过截取指定字符串来达到目的。那么下面就介绍我自己处理的办法:wxm
- 今天的第二个作品,哈哈哈哈,搞起来感觉还挺有意思的,不过代码里纸牌J,Q,K,A几个数字被我替换成了11,12,13,14......主要是
- 本文介绍了如何在Linux下安装MySQL8.0,供大家参考,具体内容如下准备工作:mysql8.0 rpm文件测试工具(比如 idea的d
- 红包分配算法代码实现发给大家,祝红包大丰收!#coding=gbkimport randomimport sys#print random.
- 本文给大家分享Python解释器安装以及PyCharm安装过程。很多朋友问小编要完整的安装教程,现分享给大家。一、Python解释器安装解释
- 八卦是种优良品质,特别是用在技术上时。来看几个Reset CSS的八卦问题吧:你知道世界上第一份reset.css在哪么?*&nb
- php本身没有提供返回毫秒数的函数,但提供了一个microtime()函数,该函数返回一个array,包含两个元素,一个是秒数,一个是小数表
- 一、必备插件🌾Chinese(中文)安装后,按快捷键Ctrl+Shift+P,输入configure languageSettings Sy
- python中对文件、文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块。得到当前工作目录,即当前Python脚本工作的目录路
- numpy norm()函数求范数函数:norm(x, ord = None, axis = None, keepdims = False)
- 一、动机最近打算折腾vn.py,但只有py27版本的,因为一向习惯使用最新稳定版的,所以不得不装py27的环境,不得不说 Python的全局
- sequence 序列sequence(序列)是一组有顺序的元素的集合(严格的说,是对象的集合,但鉴于我们还没有引入“对象”概念,暂时说元素
- 一、虚拟环境概述Python应用程序通常会使用不在标准库内的软件包和模块。应用程序有时需要特定版本的库,修复特定的错误,或者可以使用库的过时