反射操作普通变量

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

  1. golang中的反射reflect详解

    先重复一遍反射三定律: 1.反射可以将"接口类型变量"转换为"反射类型对象". 2.反射可以将"反射类型对象"转换为"接口类型变量 ...

  2. golang中的反射解析结构体标签tag

    package main import ( "fmt" "reflect" ) type resume struct { // 反射解析结构体标签tag Nam ...

  3. Golang通脉之反射

    什么是反射 官方关于反射定义: Reflection in computing is the ability of a program to examine its own structure, pa ...

  4. 七、golang中接口、反射

    一.接口定义 1.定义 interface类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量 package main import ( "fmt" ...

  5. Golang中Struct与DB中表字段通过反射自动映射 - sqlmapper

    Golang中操作数据库已经有现成的库"database/sql"可以用,但是"database/sql"只提供了最基础的操作接口: 对数据库中一张表的增删改查 ...

  6. Go 中的反射要点

    简介 反射是元数据编程的一种形式,指的是程序获得本身结构的一种能力.不同语言的反射模型实现不一样,本文中的反射,仅仅指的是Go语言中的反射模型. 类型以及接口 这个基本概念需要清晰,这里不详细展开. ...

  7. Golang中的坑二

    Golang中的坑二 for ...range 最近两周用Golang做项目,编写web服务,两周时间写了大概五千行代码(业务代码加单元测试用例代码).用Go的感觉很爽,编码效率高,运行效率也不错,用 ...

  8. 【荐】详解 golang 中的 interface 和 nil

    golang 的 nil 在概念上和其它语言的 null.None.nil.NULL一样,都指代零值或空值.nil 是预先说明的标识符,也即通常意义上的关键字.在 golang 中,nil 只能赋值给 ...

  9. 六、golang中的结构体和方法、接口

    结构体: 1.用来自定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分 4.strucr类型是值类型 5.struct类型可以嵌套 6. ...

随机推荐

  1. 会话描述协议(SDP)介绍

    1.SDP的引入 SDP最初用于Mbone(组播骨干网)上的多媒体会议.Mbone 是Internet 的一部分,它的主要特征是对IP组播技术的使用.IP组播技术比较适合实现多方会话. 基于组播的会议 ...

  2. window下对samba的清理操作

    windows清除访问samba局域网密码缓存 1.在dos窗口中输入control userpasswords2或者control keymgr.dll,然后[高级]/[密码管理],删掉保存的该机器 ...

  3. JQuery事件对象的属性和方法

    这是今天的总结,以后学习自己可以当参考书来读读.Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态.事件通常与函数结合使用,函数不会在事件发生前被执行 ...

  4. 【转】64位ORACLE客户端上plsql无法识别ORACLE_HOME解决方案

    转自:http://www.2cto.com/database/201503/386267.html 中文显示问号 转自:http://zhidao.baidu.com/link?url=qJDmsa ...

  5. [ZJOI2006]物流运输 DP 最短路

    ---题面--- 题解: 设f[i]表示到第i天的代价,cost[i][j]表示第i天到第j天采取同一种方案的最小代价.那么转移就很明显了,直接$n^2$枚举即可. 所以问题就变成了怎么获取cost数 ...

  6. Android:Google出品的序列化神器Protocol Buffer使用攻略

    习惯用 Json.XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存储格式 ...

  7. CodeForces743E. Vladik and cards 二分+状压dp

    这个题我们可以想象成_---___-----__的一个水柱它具有一遍优一遍行的性质因此可以用来二分最小值len,而每次二分后我们都要验根,we可以把这个水柱想成我们在每个数段里取前一段的那个数后一段有 ...

  8. NodeJS + PhantomJS 前端自动化资源监控

    前言:最近做前端资源监控,看了很多例子,没有达到想要的效果.首先的槽点是PhantomJS的官方文档,真鸡肋,其次是网上的例子,多数是介绍PhantomJS的用法,而并没有介绍怎么完整的去实现,跟官方 ...

  9. Ubuntu下使用mysqli-connect连接mysql时报错:ERROR 1698 (28000): Access denied for user 'root'@'localhost'

    LNMP安装好后,写了个index.php文件,里面的内容很简单,就是想测试php与mysql的通信是否正常,代码如下: <?php $host = 'localhost'; $user = ' ...

  10. angular js module 的理解

    module其实就是一个容器,里面可以装controller,service,directive,filter等, 官网的解释是:Module :A container for the differe ...