golang反射
要点
- 1.变量
- 2.反射
- 3.结构体反射
- 4.反射总结以及应用场景
一、变量介绍
1.变量的内在机制
- A、类型信息,这部分是元信息,是预定义好的
- B、值类型,这部分是程序运行过程中,动态改变的
var arr [10]int
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
type Animal struct {
Name string
age int
}
var a Animal
二、反射介绍
1.反射与空接口
- A、空接口可以存储任何类型的变量
- B、那么给你一个空接口,怎么知道里面存储的是什么东西?
- C、在运行时动态获取一个变量的类型信息和值信息,就叫反射
2.反射介绍
- A.内置包 reflect
- B.获取类型信息: reflect.TypeOf
- C.获取值信息: reflect.ValueOf
3.基本数据类型分析
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
fmt.Println("type:", reflect.TypeOf(x))
}
4.Type.Kind(),获取变量的类型
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
t := reflect.TypeOf(x)
fmt.Println("type:", t.Kind())
}
5.reflect.ValueOf, 获取变量的值相关信息
var x float64 = 3.4
v := reflect.ValueOf(x)
// 和reflect.TypeOf功能是一样的
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:",v.Kind() == reflect.Float64)
fmt.Println("value:",v.Float())
6.通过反射设置变量的值
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:",v.Kind() == reflect.Float64)
v.SetFloat(6.8)
fmt.Println("value:", v.Float())
panic,程序崩溃了。
7.通过反射设置变量的值
var x float64 = 3.4
// 传地址进去,不传地址的话,改变的是副本的值
// 所以在reflect包里直接崩溃了!!!!
v := reflect.ValueOf(&x)
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
v.SetFloat(6.8)
fmt.Println("value:",v.Float())
我靠,还报错.
8.通过反射设置变量的值
var x float64 = 3.4
// 传地址进去,不传地址的话,改变的是副本的值
// 所以在reflect包里直接崩溃了!!!!
v := reflect.ValueOf(&x)
fmt.Println("type:",v.Type())
fmt.Println("kind is float64:",v.Kind() == reflect.Float64)
// 通过Elem()获取指针指向的变量,从而完成赋值操作。
// 正常操作是通过*号来解决的,比如
// var *p int = new(int)
// *p = 100
v.Elem().SetFloat(6.8)
fmt.Println("value:",v.Float())
9.通过反射设置变量的值
var x float64 = 3.4
v := reflect.ValueOf(&x)
fmt.Println("type:",v.Type())
fmt.Println("kind is float64:",v.Kind() == reflect.Float64)
v.Elem().SetInt(100)
fmt.Println("value:",v.Float())
// 我靠,又犯贱了。
结构体反射
1.获取结构体类型相关信息
package main
import (
"fmt"
"reflect"
)
type S struct {
A int
B string
}
func main() {
s := S{23, "skidoo"}
v := reflect.ValueOf(s)
t := v.Type()
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
fmt.Printf("%d: %s %s = %v\n",i,t.Field(i).Name, f.Type(), f.Interface())
}
}
2.获取结构体类型相关信息
package main
import (
"fmt"
"reflect"
)
type S struct {
A int
B string
}
func main() {
s := S{23, "skidoo"}
v := reflect.ValueOf(s)
t := v.Type()
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
fmt.Printf("%d: %s %s = %v\n",i,t.Field(i).Name, f.Type(), f.Interface())
}
}
3.设置结构相关字段的值
package main
import (
"fmt"
"reflect"
)
type S struct {
A int
B string
}
func main() {
s := S{23, "skidoo"}
v := reflect.ValueOf(&s)
t := v.Type()
v.Elem().Field(0).SetInt(100)
for i := 0; i < v.Elem().NumField(); i++ {
f := v.Elem().Field(i)
fmt.Printf("%d: %s %s = %v\n",i, t.Elem().Field(i).Name, f.Type(), f.Interface())
}
}
4.获取结构体的方法信息
package main
import (
"fmt"
"reflect"
)
type S struct {
A int
B string
}
func (s *S) Test() {
fmt.Println("this is a test")
}
func main() {
s := S{23, "skidoo"}
v := reflect.ValueOf(&s)
t := v.Type()
v.Elem().Field(0).SetInt(100)
fmt.Println("method num:", v.NumField())
for i := 0; i < v.NumMethod(); i++ {
f := t.Method(i)
fmt.Printf("%d method, name:%v, type:%v\n", i, f.Name, f.Type)
}
}
5.调用结构体中的方法
package main
import (
"fmt"
"reflect"
)
type S struct {
A int
B string
}
func (s *S) Test() {
fmt.Println("this is a test")
}
func (s *S) SetA(a int) {
s.A = a
}
func main() {
s := S{23, "skidoo"}
v := reflect.ValueOf(&s)
m := v.MethodByName("Test")
var args1 []reflect.Value
m.Call(args1)
setA := v.MethodByName("SetA")
var args2 []reflect.Value
args2 = append(args2, reflect.ValueOf(100))
setA.Call(args2)
fmt.Printf("s:%#v\n",s)
}
6.获取结构体中的tag信息
package main
import (
"fmt"
"reflect"
)
type S struct {
F string `species:"gopher" color:"blue" json:"f"`
}
func main() {
s := S{}
st := reflect.TypeOf(s)
field := st.Field(0)
fmt.Println(field.Tag.Get("color"), field.Tag.Get("species"), field.Tag.Get("json"))
}
7.应用场景
在运行时动态获取一个变量的类型信息和值信息就叫做反射
- 1.序列化和反序列化,比如json, protobuf等各种数据协议
- 2.各种数据库的ORM, 比如gorm, sqlx等数据库中间件
- 3.配置文件解析相关的库,比如ymal ini等。
golang反射的更多相关文章
- golang反射初试
golang反射来自Go AST(Abstract Syntax Tree). reflect操作更多像traverse AST. t := reflect.TypeOf(obj) 使用TypeOf( ...
- golang 反射应用(二)
golang反射应用(二) package test import ( "reflect" "testing" ) //定义适配器 func TestRefle ...
- Golang反射机制
Go反射机制:在编译不知道类型的情况下,可更新变量.在运行时查看值.调用方法以及直接对它们的布局进行操作. 为什么使用反射 有时需要封装统一接口对不同类型数据做处理,而这些类型可能无法共享同一个接口, ...
- [golang]反射的用处--代码自动生成
背景: go语言处理db.json的时候,具体代码的变量定义和db字段.json输出的时候可能不一样. 这个时候,我们需要用tag的方式来进行定义. 例如: type MyStruct struct ...
- GOLANG 反射法则
译自[blog.golang.org/laws-of-reflection] 在计算机中, 反射是程序通过类型,检测到它自己的结构能力:是一种元编程程:也是一个具大的混淆点 在本文中,我们将通过解释反 ...
- golang 反射
参考:|--http://blog.51cto.com/speakingbaicai/1707637 |--https://studygolang.com/articles/6324 反射是在gola ...
- golang 反射中调用方法
反射中调用函数 众所周知,golang中的函数是可以像普通的int.float等类型变量那样作为值的,例如: package main import "fmt" func hell ...
- GO开发[六]:golang反射(reflect)
反射 反射:可以在运行时动态获取变量的相关信息 Import ("reflect") reflect.TypeOf,获取变量的类型,返回reflect.Type类型 refle ...
- golang反射举例
反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:并且能改变它的属性. package main import ( "f ...
随机推荐
- trueStudio笔记
1.C标准的选择 可以在项目->属性->C/C++ Build->Setting->Tool Setting->C Compiler->General中选择使用不同 ...
- go_micro相关书签
https://micro.mu/docs/cn/index.html gomicro文档 https://github.com/micro/go-micro gomicro代码 windows安装 ...
- Element-ui框架checkbox复选框回显
先看下效果是不是你需要的..... 然后废话不多说,上代码,希望能够帮助到你... <template> <div class=''> <el-form label-wi ...
- 2019/2/23Scala学习开始(Scala简介)
Scala简介 Scala是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性. Scala运行在Java虚拟机上,并兼容现有的Java程序 ...
- [cf contest 893(edu round 33)] F - Subtree Minimum Query
[cf contest 893(edu round 33)] F - Subtree Minimum Query time limit per test 6 seconds memory limit ...
- 2015-112 ado.net2
CRUD:create read update delete 七. 数据绑定数据列的转换 在gridview中添加<OnRowDataBound="GridView1_RowDataB ...
- 微信小程序电商实战(-)商城首页
首先在app.json中配置页面和底部tabbar { "pages":[ "pages/index/index", "pages/kind/kind ...
- Html5 <video>实现摄像头监控问题:html5并不支持rtsp协议,所以使用vlc进行转码,将rtsp转http流,这样<video>才可以直接播放
今天在写html5中播放旷视C2摄像头视频监控的功能,查了很多资料,才发现Html5 <video>并不支持rtsp协议.后来查到使用第三方转码才得以实现. 这里把方法写下来分享给大家. ...
- Winsock API编程介绍
相信很多人都对网络编程感兴趣,下面我们就来介绍,在网络编程中应用最广泛的编程接口Winsock API. 使用Winsock API的编程,应该了解一些TCP/IP的基础知识.虽然你可以直接使用Win ...
- java多线程面试中常见知识点
1.进程和线程 (1)进程是资源分配的最小单位,线程是程序执行的最小单位. (2)进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段.堆栈段和数据段,这种操作非 ...