程序通过反射可以在运行时访问、检测和修改自身的状态和行为。在Golang中,反射机制可以通过reflect包实现。
反射就是在程序运行时,可以访问自身结构并且做出修改的一种能力。反射机制在 Golang 中是通过 reflect 包来实现的,reflect 包提供了两个主要的类型:reflect.Type 和 reflect.Value。
Type 类型Value类型在go反射系统中,都是通过将 interface{} 转换为 Type或Value类型,然后通过对Type和Value的操作,实现相应的功能。
gofunc main() {
var num float64 = 1.2345
// 第一定律
typeOf := reflect.TypeOf(num)
fmt.Println("typeOf:", typeOf) // typeOf: float64
valueOf := reflect.ValueOf(num)
fmt.Println("valueOf:", valueOf) // valueOf:1.2345
// 第二定律
anyValue := valueOf.Interface().(float64)
fmt.Printf("anyValue: %v, %T\n", anyValue, anyValue) // anyValue: 1.2345, float64
val := reflect.ValueOf(&num)
val.Elem().SetFloat(1.23)//// 先根据地址值获取对应的实际值再修改其值
fmt.Println("修改后的值:", num) // 修改后的值: 1.23
}
这里以结构体为例
gotype User struct {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
Age int `json:"age"`
Gender string `json:"gender"`
}
func main() {
var user = User{
Username: "qianxunyimeng",
Password: "123456",
Email: "qianxunyimeng@gmail.com",
Age: 25,
Gender: "male",
}
typeUser := reflect.TypeOf(user)
fmt.Println("typeOf: ", typeUser) // typeOf: main.User
numFields := typeUser.NumField()
for i := 0; i < numFields; i++ {
field := typeUser.Field(i)
fmt.Printf("%d: name(变量名称) = %s offset(首地址偏移量) = %d "+
"anonymous(是否为匿名变量) = %t type(变量类型) = %s exported(是否可导出) = %t tag = %s\n",
i, field.Name, field.Offset, field.Anonymous, field.Type, field.IsExported(), field.Tag,
)
}
fmt.Println("===========")
//使用变量名称获取字段
if field, ok := typeUser.FieldByName("Username"); ok {
fmt.Printf("name(变量名称) = %s offset(首地址偏移量) = %d "+
"anonymous(是否为匿名变量) = %t type(变量类型) = %s exported(是否可导出) = %t tag = %s\n",
field.Name, field.Offset, field.Anonymous, field.Type, field.IsExported(), field.Tag,
)
}
fmt.Println("===========")
//根据索引获取字段
field := typeUser.FieldByIndex([]int{3})
fmt.Printf("name(变量名称) = %s offset(首地址偏移量) = %d "+
"anonymous(是否为匿名变量) = %t type(变量类型) = %s exported(是否可导出) = %t tag = %s\n",
field.Name, field.Offset, field.Anonymous, field.Type, field.IsExported(), field.Tag,
)
}
输出如下
typeOf: main.User 0: name(变量名称) = Username offset(首地址偏移量) = 0 anonymous(是否为匿名变量) = false type(变量类型) = string exported(是否可导出) = true tag = json:"username" 1: name(变量名称) = Password offset(首地址偏移量) = 16 anonymous(是否为匿名变量) = false type(变量类型) = string exported(是否可导出) = true tag = json:"password" 2: name(变量名称) = Email offset(首地址偏移量) = 32 anonymous(是否为匿名变量) = false type(变量类型) = string exported(是否可导出) = true tag = json:"email" 3: name(变量名称) = Age offset(首地址偏移量) = 48 anonymous(是否为匿名变量) = false type(变量类型) = int exported(是否可导出) = true tag = json:"age" 4: name(变量名称) = Gender offset(首地址偏移量) = 56 anonymous(是否为匿名变量) = false type(变量类型) = string exported(是否可导出) = true tag = json:"gender" =========== name(变量名称) = Username offset(首地址偏移量) = 0 anonymous(是否为匿名变量) = false type(变量类型) = string exported(是否可导出) = true tag = json:"username" =========== name(变量名称) = Age offset(首地址偏移量) = 48 anonymous(是否为匿名变量) = false type(变量类型) = int exported(是否可导出) = true tag = json:"age"
goimport (
"crypto/md5"
"encoding/hex"
"fmt"
"reflect"
)
type User struct {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
Age int `json:"age"`
Gender string `json:"gender"`
}
func (u User) GetUsername() string {
return u.Username
}
func (u *User) GetEmail() string {
return u.Email
}
func (u *User) SetPassworld(pass string) string {
md5New := md5.New()
md5New.Write([]byte(pass))
// hex转字符串
md5String := hex.EncodeToString(md5New.Sum(nil))
fmt.Println(md5String)
return md5String
}
func main() {
var user = &User{
Username: "qianxunyimeng",
Password: "123456",
Email: "qianxunyimeng@gmail.com",
Age: 25,
Gender: "male",
}
typeOf := reflect.TypeOf(user.SetPassworld)
// 获取函数的参数类型
for i := 0; i < typeOf.NumIn(); i++ {
//fmt.Println(typeOf.In(i).String())
fmt.Printf("入参类型:%s\n", typeOf.In(i).Kind()) // 入参类型:string
}
// 获取函数的返回值类型
for i := 0; i < typeOf.NumOut(); i++ {
fmt.Printf("出参类型:%s\n", typeOf.Out(i).Kind()) // 出参类型:string
}
}
goimport (
"fmt"
"reflect"
)
type People interface {
Say() string
}
type User struct {
Username string `json:"username"`
Email string `json:"email"`
Age int `json:"age"`
}
func (u *User) Say() string {
return fmt.Sprintf("Hello, my name is %s", u.Username)
}
func main() {
//首先需要获取到接口到类型
peopleType := reflect.TypeOf((*People)(nil)).Elem()
fmt.Println("people是否是一个接口: ", peopleType.Kind() == reflect.Interface) // true
// 判断User是否实现了People接口,实现接口有两种形式,指针和非指针
noPointUser := reflect.TypeOf(User{})
pointUser := reflect.TypeOf(&User{})
fmt.Println("noPointUser是否实现了People接口: ", noPointUser.Implements(peopleType)) // false
fmt.Println("pointUser是否实现了People接口: ", pointUser.Implements(peopleType)) // true
}
gotype User struct {
Username string `json:"username"`
Email string `json:"email"`
Age int `json:"age"`
}
func (u *User) Say() string {
return fmt.Sprintf("Hello, my name is %s", u.Username)
}
func main() {
user := User{
Username: "John",
Email: "john@example.com",
Age: 30,
}
userValueOf := reflect.ValueOf(&user)
username := userValueOf.Elem().FieldByName("Username")
fmt.Println("Username:", username) // Username: John
username.SetString("Tom")
fmt.Println("Username:", username) // Username: Tom
userTypeOf := userValueOf.Type()
fmt.Println("type: ", userTypeOf) // type: *main.User
fmt.Println("kind: ", userTypeOf.Kind()) // kind: ptr
}
gotype User struct {
Username string `json:"username"`
Email string `json:"email"`
Age int `json:"age"`
}
func main() {
user := User{
Username: "John",
Email: "john@example.com",
Age: 30,
}
pointUserValueof := reflect.ValueOf(&user)
fmt.Println(pointUserValueof.Type()) // *main.User
/**
func (v Value) Elem() Value
方法返回v指向的对象。
要求v必须是interface或指针。
*/
noPointUserValueof := pointUserValueof.Elem() // 获取指针指向到具体对象
fmt.Println(noPointUserValueof.Type()) // main.User
pointUserValueof = noPointUserValueof.Addr() // 转换为指针类型
fmt.Println(pointUserValueof.Type()) // *main.User
}
gotype User struct {
Username string `json:"username"`
Email string `json:"email"`
Age int `json:"age"`
}
func main() {
user := User{
Username: "John",
Email: "john@example.com",
Age: 30,
}
pointUserValueof := reflect.ValueOf(&user)
noPointUserValueof := pointUserValueof.Elem() // 获取指针指向到具体对象
// 想把reflect.Value转换为User
u := noPointUserValueof.Interface().(User) // func (v Value) Interface() (i any) 这里需要把any强制转换为User
fmt.Println(u.Username) // John
}
gotype User struct {
Username string `json:"username"`
Email string `json:"email"`
Age int `json:"age"`
}
func main() {
// 情形一
var i interface{} // 没有指向具体的值
v := reflect.ValueOf(i)
fmt.Println("kind:", v.Kind()) // kind: invalid
if !v.IsValid() {
fmt.Println("value is invalid")
}
// 情形二
var user *User = nil
v = reflect.ValueOf(user) // value指向一个nil
if v.IsValid() {
fmt.Printf("v持有的值是nil %t\n", v.IsNil()) // v持有的值是nil true
}
// 情形三
var u User // 只声明没有初始化,里面的值是零值
v = reflect.ValueOf(u)
if v.IsValid() {
fmt.Printf("v持有的值是零值 %t\n", v.IsZero()) // v持有的值是零值 true
}
}
gotype User struct {
Username string `json:"username"`
age int `json:"age"`
}
func main() {
var user = User{
Username: "sql",
age: 24,
}
valueOf := reflect.ValueOf(&user)
valueOf.Elem().FieldByName("Username").SetString("Tom")
fmt.Println(user.Username) // Tom
ageValue := valueOf.Elem().FieldByName("age")
if ageValue.CanSet() {
ageValue.SetInt(18)
} else {
fmt.Println("私有成员不能修改") // 私有成员不能修改
}
}
gotype User struct {
Username string `json:"username"`
age int `json:"age"`
}
func (u *User) GetName() string {
return u.Username
}
func (u *User) SetName(username string) {
u.Username = username
}
func main() {
var user = User{
Username: "Tom",
age: 18,
}
valueOf := reflect.ValueOf(&user)
methodByname := valueOf.MethodByName("GetName")
// 没有参数就传递空切片
result := methodByname.Call([]reflect.Value{})
for _, v := range result {
fmt.Println(v.Interface()) // Tom
}
methodByname = valueOf.MethodByName("SetName")
methodByname.Call([]reflect.Value{reflect.ValueOf("Jerry")})
fmt.Println(user) // {Jerry 18}
}
go// 通过反射的方式创建结构体
// 首先获取结构体对应的Type
userType := reflect.TypeOf(User{})
userValue := reflect.New(userType) // 相当于 valueOf(&User{}) 是一个指针类型的值
userValue.Elem().FieldByName("Username").SetString("tom")
user := userValue.Elem().Interface().(User)
fmt.Println(user) // {tom 0}
type User struct { Username string `json:"username"` Age int `json:"age"` } func (u *User) GetName() string { return u.Username } func (u *User) SetName(username string) { u.Username = username } func main() { // 通过反射的方式创建切片 sliceType := reflect.TypeOf([]User{}) sliceValue := reflect.MakeSlice(sliceType, 1, 3) sliceValue.Index(0).FieldByName("Username").SetString("jerry") sliceValue.Index(0).FieldByName("Age").Set(reflect.ValueOf(20)) fmt.Println(sliceValue) // [{jerry 20}] var newUser = User{ Username: "Tom", Age: 23, } sliceValue = reflect.Append(sliceValue, reflect.ValueOf(newUser)) fmt.Println(sliceValue) // [{jerry 20} {Tom 23}] // 通过反射的方式扩容切片 } func expandSlice(s []interface{}, newCap int) error { v := reflect.ValueOf(s) if v.Kind() != reflect.Slice { return errors.New("expandSlice() interface argument must be a slice") } if newCap <= v.Cap() { return nil } // 创建一个新的切片,容量为新的容量,长度不变 newSlice := reflect.MakeSlice(v.Type(), v.Len(), newCap) reflect.Copy(newSlice, v) //将旧切片拷贝到新切片 ptr := reflect.ValueOf(s).Elem() ptr.Set(newSlice) return nil }


本文作者:繁星
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!