要点

  • 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反射的更多相关文章

  1. golang反射初试

    golang反射来自Go AST(Abstract Syntax Tree). reflect操作更多像traverse AST. t := reflect.TypeOf(obj) 使用TypeOf( ...

  2. golang 反射应用(二)

    golang反射应用(二) package test import ( "reflect" "testing" ) //定义适配器 func TestRefle ...

  3. Golang反射机制

    Go反射机制:在编译不知道类型的情况下,可更新变量.在运行时查看值.调用方法以及直接对它们的布局进行操作. 为什么使用反射 有时需要封装统一接口对不同类型数据做处理,而这些类型可能无法共享同一个接口, ...

  4. [golang]反射的用处--代码自动生成

    背景: go语言处理db.json的时候,具体代码的变量定义和db字段.json输出的时候可能不一样. 这个时候,我们需要用tag的方式来进行定义. 例如: type MyStruct struct ...

  5. GOLANG 反射法则

    译自[blog.golang.org/laws-of-reflection] 在计算机中, 反射是程序通过类型,检测到它自己的结构能力:是一种元编程程:也是一个具大的混淆点 在本文中,我们将通过解释反 ...

  6. golang 反射

    参考:|--http://blog.51cto.com/speakingbaicai/1707637 |--https://studygolang.com/articles/6324 反射是在gola ...

  7. golang 反射中调用方法

    反射中调用函数 众所周知,golang中的函数是可以像普通的int.float等类型变量那样作为值的,例如: package main import "fmt" func hell ...

  8. GO开发[六]:golang反射(reflect)

    反射 反射:可以在运行时动态获取变量的相关信息 ​ Import ("reflect") reflect.TypeOf,获取变量的类型,返回reflect.Type类型 refle ...

  9. golang反射举例

    反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:并且能改变它的属性. package main import ( "f ...

随机推荐

  1. 【设计模式】工厂模式(Factory Pattern)

    [前言] 很多时候我们编写了好几个接口的实现类,这些实现类分别有不同特性,用在不同的情景下.而我们对于这些实现类,也往往不会对外暴露内部增加的方法,只希望外部调用接口的方法,在这种情况下,我们没必要让 ...

  2. oralce问题

    死锁,如果较多使用存储过程杀死 create or replace procedure killer is    v_obj varchar2(200);    v_sql varchar2(500) ...

  3. python实现汉诺塔问题

    汉诺塔问题可以简单描述成为将a柱子上的圆盘按一定规则借助b柱子完美地复制到c柱子上.现假设有a,b,c三根柱子,a柱子上的圆盘从上到下依次标号为1,2,3,……,n,且为递增状态.规则:每次移动一个盘 ...

  4. Confluence 6 针对 'unmigrated-wiki-markup' 宏重新尝试合并

    在签名的章节中,我们主要是针对没有完全合并完成余下的为合并内容的异常处理.最常见的情况是内容以及被合并了,但是页面使用 wiki 标记的内容没有被合并,通常这些 wiki 标记的内容使用了 'unmi ...

  5. 最简单的RPC框架实现

    通过java原生的序列化,Socket通信,动态代理和反射机制,实现一个简单的RPC框架,由三部分组成: 1.服务提供者,运行再服务端,负责提供服务接口定义和服务实现类 2.服务发布者,运行再RPC服 ...

  6. 学习mysql,记录下常用的命令行语句

    MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用 ...

  7. STRANS一:简单的XML转换

    心情不好,泥总把表妹微信给冰冰了,心塞... 1.简单的单层结构: <?sap.transform simple?> <tt:transform xmlns:tt="htt ...

  8. 【macOS】 在OpenCV下训练Haar特征分类器

    本教程基于以下环境 macOS 10.12.6,OpenCV 3.3.0,python 3.6.由于网上基于masOS系统的教程太少,想出一篇相关教程造福大家-本文旨在学习如何在opencv中基于ha ...

  9. Win10安装LoadRunner11

    一.下载 地址:http://www.51testing.com/?uid-4827-action-viewspace-itemid-225451 二.安装 本来想写,结果和别人的一样就不写了:htt ...

  10. lumion的物体系统5.30

    1.“自然"点击这棵树.可以打开自然库.不同的植物分类有很多页数. 选择一棵树,自动返回页面单击鼠标左键可以种植这个树.成排种树:点击”人群安置“点击我们想安置的起点.再点击终点.用鼠标右键 ...