golang中的反射
反射操作普通变量
package main
import (
"fmt"
"reflect"
)
func main(){
a := 1
//reflect.TypeOf获取类型
fmt.Println(reflect.TypeOf(a)) //int
//查看占的字节
fmt.Println(reflect.TypeOf(a).Size())//8
//TypeOf获取的是reflect.Type类型,可以转化成字符串
fmt.Println(reflect.TypeOf(a).Name() == "int") //true
fmt.Println(reflect.TypeOf(a).String() == "int") //true
//对于一个interface{},我们便可以通过这种方式来判断到底是什么类型
func(val interface{}){
switch t:=reflect.TypeOf(val).String();t {
case "int":
fmt.Println("val的类型为int")
case "string":
fmt.Println("val的类型为string")
case "int32":
fmt.Println("val的类型为int32")
case "[]int":
fallthrough
case "[]string":
fmt.Println("val的类型为切片")
}
}([]int{}) //val的类型为切片
b := 'x'
//获取的是reflect.Value类型,注意此时是没有办法比较的
fmt.Println(reflect.ValueOf(b)) //120
/*
//获取相应的值,但你要提前知道类型,然后调用相应的方法
fmt.Println(reflect.ValueOf(b).Int())
fmt.Println(reflect.ValueOf(b).String())
fmt.Println(reflect.ValueOf(b).Float())
*/
//不过也可以使用interface进行转化,会自动推断出具有真正类型的值
fmt.Println(reflect.ValueOf(b).Interface() == 'x') //true
//使用kind()或者Type()也可以获取值类型,再转换成String
fmt.Println(reflect.ValueOf(b).Kind().String() == "int32")//true
fmt.Println(reflect.ValueOf(b).Type().String() == "int32")//true
//如何设置一个值
name:="mashiro"
//这里必须要传递指针进去,因为golang是值传递,传递值的话会单独拷贝一份。Elem()是为了得到变量的指针
val := reflect.ValueOf(&name).Elem()
fmt.Println(val.CanSet()) //true
val.SetString("satori")
fmt.Println(name)//satori
}
反射操作结构体
package main
import (
"fmt"
"reflect"
)
type Girl struct {
Name string
Age int
Gender string
Length int
}
//给结构体定义几个方法
func (g Girl)Info(){
fmt.Println("info")
}
func (g Girl)Info1(){
fmt.Println("info1")
}
func (g Girl)Info2(){
fmt.Println("info2")
}
func main(){
//先来如何获取结构体的类型
g := Girl{"satori",16,"f",155}
//我们之前看用Kind()和Type()获取的类型都是一样的,但那只是针对于int string之类的
//当换成结构体的时候,我们看到,kind()的范围比较大,得到的是一个struct,而Type()得到的是具体的struct类型
fmt.Println(reflect.ValueOf(g).Kind()) //struct
fmt.Println(reflect.ValueOf(g).Type()) //main.girl
//所以我们也可以判断是不是结构体,怎么判断呢?
//注意使用Kind()得到的是一个reflect.Value类型,因此要是用reflect.Struct判断
fmt.Println(reflect.ValueOf(g).Kind() == reflect.Struct) //true
//如果使用字符串判断的话,那么可以转化一下
fmt.Println(reflect.ValueOf(g).Kind().String() == "struct")//true
//使用TypeOf(),Name()和String()获取的都是字符串,但是Name()不包含main
fmt.Println(reflect.TypeOf(g).Name() == "girl") //true
fmt.Println(reflect.TypeOf(g).String() == "main.girl") //true
//再来看看获取结构体内部元素的属性
//如何获取结构体的字段的数量
fmt.Println(reflect.ValueOf(g).NumField(), reflect.TypeOf(g).NumField()) //4 4
//如何获取结构体的方法的数量,注意方法名必须要大写,否则检测不到
fmt.Println(reflect.ValueOf(g).NumMethod(), reflect.TypeOf(g).NumMethod()) //3 3
//调用方法,只能通过ValueOf,Call中必须传入[]reflect.Value类型
var params []reflect.Value
reflect.ValueOf(g).Method(0).Call(params) //info
reflect.ValueOf(g).Method(1).Call(params) //info1
reflect.ValueOf(g).Method(2).Call(params) //info2
//遍历结构体内部字段
t:=reflect.TypeOf(g)
v:=reflect.ValueOf(g)
for i:=0;i<t.NumField();i++{
//Field(i)获取第i个字段属性,Name则是获取名字。Type则是获取对应类型,如果比较的话,可以使用String()转成字符串类型
fmt.Println("字段名:",t.Field(i).Name," 值类型:", t.Field(i).Type.String())
/*
字段名: Name 值类型: string
字段名: Age 值类型: int
字段名: Gender 值类型: string
字段名: Length 值类型: int
*/
}
for i:=0;i<v.NumField();i++{
fmt.Println("值类型:",v.Field(i).Type().String(), " 值类型:", v.Field(i).Kind().String(), " 值:", v.Field(i).Interface())
/*
值类型: string 值类型: string 值: satori
值类型: int 值类型: int 值: 16
值类型: string 值类型: string 值: f
值类型: int 值类型: int 值: 155
*/
}
}
反射操作函数
package main
import (
"fmt"
"reflect"
"runtime"
)
func foo(){}
func main(){
t:=reflect.TypeOf(foo)
v:=reflect.ValueOf(foo)
fmt.Println(t.Name()) // 啥也没有
fmt.Println(t.Kind(), t.Kind().String() == "func") // func true
fmt.Println(t.String(), t.String() == "func()") //func() true
fmt.Println(v.Type())//func()
fmt.Println(v.Kind())// func
//我们在结构体中,t.Name()打印了是girl,t.String()打印的main.girl
//v.Type()打印的是main.girl。这里Kind()打印的是类型本身是一个func和结构体类似,但是v.Type和t.Name()和t.String()应该打印函数名啊
//按照我们结构体的例子来说,t.Name()应该是foo,t.String()和v.Type()应该是main.foo才对啊,可这里不是,那我们如何获取函数名呢?
fmt.Println(v.Interface()) //0x48e110, 这里打印的则是函数的内存地址,普通变量打印的是值
//目前是拿不到函数名了,但是有没有其他的办法呢?虽然有点复杂,但还是可以拿到的
pointer:=reflect.ValueOf(foo).Pointer()
fmt.Println(runtime.FuncForPC(pointer).Name()) //main.foo
fmt.Println(runtime.FuncForPC(pointer).Name() == "main.foo") //true
}
golang中的反射的更多相关文章
- golang中的反射reflect详解
先重复一遍反射三定律: 1.反射可以将"接口类型变量"转换为"反射类型对象". 2.反射可以将"反射类型对象"转换为"接口类型变量 ...
- golang中的反射解析结构体标签tag
package main import ( "fmt" "reflect" ) type resume struct { // 反射解析结构体标签tag Nam ...
- Golang通脉之反射
什么是反射 官方关于反射定义: Reflection in computing is the ability of a program to examine its own structure, pa ...
- 七、golang中接口、反射
一.接口定义 1.定义 interface类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量 package main import ( "fmt" ...
- Golang中Struct与DB中表字段通过反射自动映射 - sqlmapper
Golang中操作数据库已经有现成的库"database/sql"可以用,但是"database/sql"只提供了最基础的操作接口: 对数据库中一张表的增删改查 ...
- Go 中的反射要点
简介 反射是元数据编程的一种形式,指的是程序获得本身结构的一种能力.不同语言的反射模型实现不一样,本文中的反射,仅仅指的是Go语言中的反射模型. 类型以及接口 这个基本概念需要清晰,这里不详细展开. ...
- Golang中的坑二
Golang中的坑二 for ...range 最近两周用Golang做项目,编写web服务,两周时间写了大概五千行代码(业务代码加单元测试用例代码).用Go的感觉很爽,编码效率高,运行效率也不错,用 ...
- 【荐】详解 golang 中的 interface 和 nil
golang 的 nil 在概念上和其它语言的 null.None.nil.NULL一样,都指代零值或空值.nil 是预先说明的标识符,也即通常意义上的关键字.在 golang 中,nil 只能赋值给 ...
- 六、golang中的结构体和方法、接口
结构体: 1.用来自定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分 4.strucr类型是值类型 5.struct类型可以嵌套 6. ...
随机推荐
- Micro Average vs Macro average Performance in a Multiclass classification setting
整理摘自 https://datascience.stackexchange.com/questions/15989/micro-average-vs-macro-average-performanc ...
- PAT——乙级1006:换个格式输出整数&乙级1021:个位数统计&乙级1031:查验身份证
1006 换个格式输出整数 (15 point(s)) 让我们用字母 B 来表示“百”.字母 S 表示“十”,用 12...n 来表示不为零的个位数字 n(<10),换个格式来输出任一个不超过 ...
- POJ 1463 Strategic game(二分图最大匹配)
Description Bob enjoys playing computer games, especially strategic games, but sometimes he cannot f ...
- STL应用——hdu1702(队列+堆栈)
水题 练习一下堆栈和队列的使用 #include <iostream> #include <cstdio> #include <algorithm> #includ ...
- C++结构体排序
在C++中,对结构体的排序方式比C语言丰富的多.在C语言中,我们主要是通过qsort进行排序操作(抛开手写排序算法不说). 在C++<algorithm>中,有一个十分强大的排序函数sor ...
- jQuery添加、移除、改变class属性
jQuery中一般有3个关于改变元素class的函数addClass.removeClass.toggleClass addClass描述: 为每个匹配的元素添加指定的样式类名$('div').add ...
- 用AngularJS操作DOM
在angular中使用第三方插件时最好都封装到指令(directives)中去,DOM操作也最好都解构到指令中. <!DOCTYPE html> <html lang="e ...
- IE6,7,8支持css圆角
我们知道Webkit内核的浏览器支持-webkit-border-radius: 10px;属性(10px是圆角半径),可以直接解析出圆角;Firefox浏览器支持-moz-border-radius ...
- SNMP协议介绍
SNMP协议介绍 一.什么是SNMP SNMP:“简单网络管理协议”,用于网络管理的协议.SNMP用于网络设备的管理.SNMP的工作方式:管理员需要向设备获取数据,所以SNMP提供了 “读”操作:管理 ...
- 种树 by yoyoball [树分块+bitset]
题面 给定一棵树,有点权 每次询问给出一些点对,求这些点对之间的路径的并集上不同权值的个数,以及这些权值的$mex$ 思路 先考虑只有一对点对,只询问不同权值个数的问题:树上莫队模板题 然后加个$me ...