golang:reflect(反射)基本使用

Posted live4m

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang:reflect(反射)基本使用相关的知识,希望对你有一定的参考价值。


reflect获取type:

package main

import (
	"fmt"
	"reflect"
)

type Node struct {
	val  int
	next *Node
}

func reflectOfType(x interface{}) {
	t := reflect.TypeOf(x)
	//type
	fmt.Printf("type:%v \\n", t)
	//type分为name和kind,kind是底层数据类型
	fmt.Printf("type.Name:%v, type.Kind:%v\\n\\n", t.Name(), t.Kind())
}
func TypeTest() {
	var x int64 = 1
	reflectOfType(x)

	var y float64 = 2.5
	reflectOfType(y)

	var z Node = Node{val: 1, next: nil}
	reflectOfType(z)
}
func main() {
	TypeTest()
}
/*
运行结果:

type:int64
type.Name:int64, type.Kind:int64

type:float64
type.Name:float64, type.Kind:float64

type:main.Node
type.Name:Node, type.Kind:struct
*/

reflect获取value

package main

import (
	"fmt"
	"reflect"
)

func reflectOfValue(x interface{}) {
	v := reflect.ValueOf(x)
	switch v.Kind() { //Kind
	case reflect.Int64: //这里的类型是reflect.Kind,所以switch传入的必须也是Kind
		fmt.Printf("type:%v, value:%v \\n", v.Type(), int64(v.Int()))
	case reflect.Float64:
		fmt.Printf("type:%v, value:%v \\n", v.Type(), float64(v.Float()))
	}
}

func ValueTest() {
	var x int64 = 1
	reflectOfValue(x)

	var y float64 = 2.5
	reflectOfValue(y)
}

func main() {
	ValueTest()
}
/*
运行结果:

type:int64, value:1 
type:float64, value:2.5 
*/

reflect修改值

package main

import (
	"fmt"
	"reflect"
)

func reflectOfSetValue11111(x interface{}) {
	v := reflect.ValueOf(x)
	switch v.Kind() {
	case reflect.Float64:
		v.SetFloat(200.5)
	}
}
func reflectOfSetValue22222(x interface{}) {
	v := reflect.ValueOf(x)
	fmt.Println(v.Elem().Kind())
	switch v.Elem().Kind() {
	case reflect.Float64:
		v.Elem().SetFloat(200.5)
	}
}
func SetValueTest() {
	var y float64 = 2.5
	// fmt.Printf("y:%v\\n", y)
	// reflectOfSetValue1(y) //错误用法1:传值,会引发panic,函数内部修改的是变量的副本
	// fmt.Printf("y:%v\\n", y)
	fmt.Println("test2:")
	fmt.Printf("y:%v\\n", y)
	reflectOfSetValue11111(&y) //错误用法2,虽然穿的是指针,但是反射取到的是指针类型,不会进入switch
	fmt.Printf("y:%v\\n", y)    //值不会变

	fmt.Println()

	fmt.Println("test3:")
	reflectOfSetValue22222(&y) //正确用法,穿指针,函数内部先对指针取值再修改
	fmt.Printf("y:%v\\n", y)    //值变了
}
func main() {
	SetValueTest()
}
/*
运行结果:

test2:
y:2.5
y:2.5

test3:
float64
y:200.5
*/

isNil()和isValid():

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string
	Age  int
}

func (p Person) GetName() {
	fmt.Println(p.Name)
}

func reflectOfIsnil(x interface{}) {
	v := reflect.ValueOf(x)
	f := v.IsNil()
	fmt.Println(f)
}
func NilTest() { //Isnil()判断是否为nil
	// var x int
	// reflectOfIsNil(x)//错误用法:传入不可能为nil的值,会引发panic

	var y []int       //slice
	reflectOfIsnil(y) //Isnil()=true

	var z []int = []int{1, 2, 3}
	reflectOfIsnil(z) //Isnil()=false
}

func reflectOfIsvalid(x interface{}) {
	v := reflect.ValueOf(x)
	f := v.IsValid()
	fmt.Println(f)
}

func ValidTest() {
	var x *int
	fmt.Println(x) //虽然x是nil,但是Isvalid()=true
	reflectOfIsvalid(x)

	reflectOfIsvalid(nil) //Isvalid()=false
}
func ValidTest2() {
	//IsValue可以用来判断结构体中是否有某个字段
	var t Person = Person{Name: "name", Age: 11}
	fmt.Println("Field1:", reflect.ValueOf(t).FieldByName("Name").IsValid()) //true
	fmt.Println("Field2:", reflect.ValueOf(t).FieldByName("name").IsValid()) //false,由此可见:字段名大小写敏感
	//也可以用来判断结构体是否实现了某个方法
	fmt.Println("Method1:", reflect.ValueOf(t).MethodByName("GetName").IsValid()) //true
	fmt.Println("Method2:", reflect.ValueOf(t).MethodByName("Getname").IsValid()) //false,大小写敏感

	//也可以用来判断map是否存在某个键
}
func main() {
	fmt.Println("Isnil() Test:")
	NilTest()

	fmt.Println()

	fmt.Println("IsValid() Test:")
	ValidTest()

	fmt.Println()

	fmt.Println("IsValid() Test2:")
	ValidTest2()
}
/*
运行结果:
Isnil() Test:
true
false

IsValid() Test:
<nil>
true
false

IsValid() Test2:
Field1: true
Field2: false
Method1: true
Method2: false
*/

获取结构体字段信息:

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string `json:"111"`
	Age  int
}

func structTest() {
	t := Person{Name: "abc", Age: 10}
	v := reflect.TypeOf(t)
	for i := 0; i < v.NumField(); i++ {
		f := v.Field(i)
		fmt.Println(f.Name, f.Type)
		fmt.Println("Tag:", f.Tag.Get("json")) //f.Tag有一个Get方法
	}
	f, ok := v.FieldByName("name")
	if ok { //找得到则f为对于的Field
		fmt.Println(f.Name)
	} else { //找不到则为一个包含nil的结构体,可以用Isnil()判断是否为nil
		fmt.Printf("%T,%v", f, f)
	}
	/*
		Field结构体:
		type StructField struct {
			Name string
			PkgPath string
			Type      Type      // field type
			Tag       StructTag // field tag string
			Offset    uintptr   // offset within struct, in bytes
			Index     []int     // index sequence for Type.FieldByIndex
			Anonymous bool      // is an embedded field
		}
	*/
}
func main() {
	structTest()
}

获取结构体方法:

待补


以上是关于golang:reflect(反射)基本使用的主要内容,如果未能解决你的问题,请参考以下文章

golang反射

Golang 反射机制 reflect.TypeOf reflect.ValueOf字符串处理

Golang 反射机制 reflect.TypeOf reflect.ValueOf字符串处理

golang之反射

golang基础--reflect反射

Golang反射机制的实现分析——reflect.Type方法查找和调用