Go语言反射

反射是一种在运行时操作不同类型对象的能力,它可以让程序动态地获取和修改对象的类型、值、方法等信息。

Go 语言中提供了 reflect 包来支持反射功能,它包含了两个重要的类型:reflect.Type 和 reflect.Value,以及两个重要的函数:reflect.TypeOf 和 reflect.ValueOf。

reflect.Type 表示一个对象的类型信息,它包含了对象的名称、大小、对齐方式、方法集等元数据。

reflect.Value 表示一个对象的值信息,它包含了对象的具体数据和类型指针。

reflect.TypeOf 函数接受一个 interface{} 类型的参数,返回该参数对应的 reflect.Type 类型。

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	p := Person{"Alice", 20}
	t := reflect.TypeOf(p)
	fmt.Println(t.Name()) // Person
	fmt.Println(t.Kind()) // struct
}

reflect.ValueOf 函数接受一个 interface{} 类型的参数,返回该参数对应的 reflect.Value 类型。通过 reflect.Type 和 reflect.Value 类型,我们可以获取和修改对象的各种属性和行为。

package main

import (
	"fmt"
	"reflect"
)

type test struct {
	a int64
	b string
	c []uint8
}

func (t *test) SetIndexedField(index int, value interface{}) error {
	v := reflect.ValueOf(t).Elem()
	field := v.Field(index)
	if !field.CanSet() {
		return fmt.Errorf("Cannot set field %d", index)
	}
	fieldType := field.Type()
	val := reflect.ValueOf(value)
	if val.Type().ConvertibleTo(fieldType) {
		val = val.Convert(fieldType)
	} else {
		return fmt.Errorf("Cannot convert %v to %v", val.Type(), fieldType)
	}
	field.Set(val)
	return nil
}

func main() {
	var t = test{10, "test string", []uint8{1, 2, 3, 4}}
	fmt.Println(t) // {10 test string [1 2 3 4]}
	t.SetIndexedField(0, 5)          // set a to 5
	t.SetIndexedField(1, "new string") // set b to "new string"
	t.SetIndexedField(2, []uint8{8, 9}) // set c to []uint8{8,9}
	fmt.Println(t)                    // {5 new string [8 9]}
}

使用 Kind 方法判断对象属于哪种基础类型(如 int, string, slice 等)。

package main



import (

 "fmt"

 "reflect"

)



func main() {

 var x int = 100

 var y string = "hello"

 var z []int = []int{1, 2, 3}



 fmt.Println(reflect.TypeOf(x).Kind()) // int

 fmt.Println(reflect.TypeOf(y).Kind()) // string

 fmt.Println(reflect.TypeOf(z).Kind()) // slice

}

使用 NumField 和 Field 方法遍历结构体中的字段。

package main



import (

 "fmt"

 "reflect"

)



type Person struct {

 Name string

 Age int

}



func main() {

 p := Person{"Alice", 20}

 t := reflect.TypeOf(p)

 v := reflect.ValueOf(p)



 for i := 0; i < t.NumField(); i++ {

  f := t.Field(i)

  fmt.Printf("field name: %s\n", f.Name)

  fmt.Printf("field type: %s\n", f.Type)

  fmt.Printf("field value: %v\n", v.Field(i))

 }

}

使用 NumMethod 和 Method 方法调用对象上的方法。

package main



import (

 "fmt"

 "reflect"

)



type Animal struct {

 Name string

}



func (a Animal) Speak() {

 fmt.Printf("%s says hello\n", a.Name)

}



func (a Animal) Eat(food string) {

 fmt.Printf("%s eats %s\n", a.Name, food)

}



func main() {

 a := Animal{"Dog"}

 t := reflect.TypeOf(a)

 v := reflect.ValueOf(a)



 for i := 0; i < t.NumMethod(); i++ {

  m := t.Method(i)

  fmt.Printf("method name: %s\n", m.Name)

  v.Method(i).Call(nil) // call method without arguments

 }



 args := []reflect.Value{reflect.ValueOf("bone")}

 v.MethodByName("Eat").Call(args) // call method with arguments

}

使用 Elem 方法获取指针或者接口指向的元素。

package main



import (

 "fmt"

 "reflect"

)



type Shape interface {

 Draw()

}



type Circle struct {

 R float64

}



func (c Circle) Draw() {

 fmt.Printf("draw a circle with radius %.2f\n", c.R)

}



func main() {

 var s Shape = Circle{10.0}

 t1 := reflect.TypeOf(s) // interface type

 t2 := reflect.TypeOf(&s) // pointer type

 e1 := t1.Elem() // concrete type (Circle)

 e2 := t2.Elem().Elem() // concrete type (Circle)

 fmt.Println(t1, e1) // Shape Circle

 fmt.Println(t2, e2) // *Shape Circle



 v1 := reflect.ValueOf(s) // interface value 

 v2 := reflect.ValueOf(&s) // pointer value 

 e3 := v1.Elem() // concrete value (Circle{10})

 e4 := v2.Elem().Elem() // concrete value (Circle{10})

 fmt.Println(v1, e3) // <Circle Value> {10}

 fmt.Println(v2, e4) // <*Shape Value> {10}

}

使用 CanSet 方法判断对象是否可寻址和可修改。

package main



import (

 "fmt"

 "reflect"

)



func main() {

 x := 100 // x is not addressable and not settable 

 y := &x // y is addressable but not settable 

 z := reflect.ValueOf(&x).Elem() // z is addressable and settable 



 vx:= reflect.ValueOf(x)

 vy:= reflect.ValueOf(y)

 vz:= z



 fmt.Println(vx.CanSet()) // false 

 fmt.Println(vy.CanSet()) // false 

 fmt.Println(vz.CanSet()) // true

}

使用 reflect.New 方法创建指定类型的对象。

package main



import (

 "fmt"

 "reflect"

)



type Person struct {

 Name string

 Age int

}



func main() {

 t := reflect.TypeOf(Person{})

 v := reflect.New(t) // create a pointer to Person 

 fmt.Println(v.Type()) // *Person 

 fmt.Println(v.Kind()) // ptr 

 fmt.Println(v.Elem().Type()) // Person 

 fmt.Println(v.Elem().Kind()) // struct 



 p := v.Interface().(*Person) // convert to Person pointer 

 p.Name = "Bob"

 p.Age = 30

 fmt.Println(p) // &{Bob 30}

}

使用 reflect.MakeSlice 和 reflect.Append 方法创建和扩展切片。

package main



import (

 "fmt"

 "reflect"

)



func main() {

 t := reflect.TypeOf([]int{}) // slice type 

 v := reflect.MakeSlice(t, 0, 10) // create a slice with len=0 and cap=10 

 fmt.Println(v.Len(), v.Cap()) // 0 10 



 v = reflect.Append(v, reflect.ValueOf(1)) // append an element 

 v = reflect.AppendSlice(v, reflect.ValueOf([]int{2, 3})) // append another slice 



 s := v.Interface().([]int) // convert to []int 

 fmt.Println(s) // [1 2 3]

}

使用 reflect.MakeMap 和 reflect.SetMapIndex 方法创建和修改映射。

package main



import (

 "fmt"

 "reflect"

)



func main() {

 t := reflect.TypeOf(map[string]int{}) // map type 

 v := reflect.MakeMap(t) // create a map 



 k1 := reflect.ValueOf("one") // key value 

 v1 := reflect.ValueOf(1) // value value 



 k2 := reflect.ValueOf("two") // key value 

 v2 := reflect.ValueOf(2) // value value 



 v.SetMapIndex(k1, v1) // set map["one"] = 1

 v.SetMapIndex(k2, v2) // set map["two"] = 2



 m := v.Interface().(map[string]int)

使用 reflect.StructTag 方法获取结构体字段上的标签。

package main



import (

 "fmt"

 "reflect"

)



type Person struct {

 Name string `json:"name"`

 Age int `json:"age"`

}



func main() {

 t := reflect.TypeOf(Person{})

 f1 := t.Field(0) // get the first field 

 f2 := t.Field(1) // get the second field 



 fmt.Println(f1.Tag.Get("json")) // name 

 fmt.Println(f2.Tag.Get("json")) // age

}

使用 reflect.MakeFunc 方法创建一个函数对象。

package main



import (

 "fmt"

 "reflect"

)



func main() {

 t := reflect.FuncOf([]reflect.Type{reflect.TypeOf(0)}, []reflect.Type{reflect.TypeOf("")}, false) // create a function type of func(int) string 

 v := reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value { // create a function value of that type 

  n := args[0].Int() // get the first argument as int 

  s := fmt.Sprintf("%d", n) // convert it to string 

  return []reflect.Value{reflect.ValueOf(s)} // return a slice of values containing s

 })



 f := v.Interface().(func(int) string) // convert to func(int) string 

 fmt.Println(f(100)) // 100

}

使用 reflect.DeepEqual 方法比较两个对象是否相等。

package main

import (
	"fmt"
	"reflect"
)

type person struct {
	name string
	age  int
}

func main() {
	p1 := person{"Alice", 20}
	p2 := person{"Alice", 20}
	p3 := person{"Bob", 25}

	fmt.Println(reflect.DeepEqual(p1, p2)) // true
	fmt.Println(reflect.DeepEqual(p1, p3)) // false
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值