go的结构体和反射分析

1.go的结构体分析

        本文是在go1.19.10的背景下,作为记录用,为了防止遗忘。

1.结构体函数的分析

  测试代码

type User struct {
	Id   int
	Name string
	Age  int
}


func (u User) TestUserNoPtr(name string) {
	u.Name = name
}

func (u *User) TestUserPtr(name string) {
	u.Name = name
}


func TestReflectStruct(t *testing.T) {
	userOnePtr := &User{1, "no-modify", 25}
	userOnePtr.TestUserNoPtr("modify")
	fmt.Printf("struct(*user)    func(u User)  u=%v \n", userOnePtr)

	userTwoPtr := &User{1, "no-modify", 25}
	userTwoPtr.TestUserPtr("modify")
	fmt.Printf("struct(*user)    func(u *User)  u=%v\n", userTwoPtr)

	userOne := User{1, "no-modify", 25}
	userOne.TestUserNoPtr("modify")
	fmt.Printf("struct(user)    func(u User)  u=%v\n", userOne)

	userTwo := User{1, "no-modify", 25}
	userTwo.TestUserPtr("modify")
	fmt.Printf("struct(user)    func(u *User)  u=%v\n", userTwo)
}

       注意上面的测试函数,并没有用非常标准的测试函数检测,而是直接打印出来,这样是为了结果更加清晰

        最后的结果

struct(*user)    func(u User)  u=&{1 no-modify 25} 
struct(*user)    func(u *User)  u=&{1 modify 25}
struct(user)    func(u User)  u={1 no-modify 25}
struct(user)    func(u *User)  u={1 modify 25}

        从其中可以看出结构体指针可以调用自己的receiver是指针和非指针的函数,同样结构体也可以调用调用自己的receiver是指针和非指针的函数,但是数值的真正的改变只和receiver有关,是指针才会改变。

2.结构体函数的反射的分析

        测试代码

//和前面的一样,加个接口
type IUser interface {
	TestUserNoPtr(name string)
	TestUserPtr(name string)
}

func TestReflectStruct(t *testing.T) {
	userPtr := &User{1, "no-modify", 25}
	userPtrType := reflect.TypeOf(userPtr)
	userPtrValue := reflect.ValueOf(userPtr)
	for i := 0; i < userPtrType.NumMethod(); i++ {
		m := userPtrType.Method(i)
		fmt.Printf("%v: %v\n", m, m.IsExported())
	}
	if userPtrType.Implements(reflect.TypeOf((*IUser)(nil)).Elem()) {
		if f, ok := userPtrValue.Interface().(IUser); ok {
			f.TestUserNoPtr("modify")
			fmt.Printf("struct(*user)    func(u User)  u=%v \n", userPtr)
			f.TestUserPtr("modify")
			fmt.Printf("struct(*user)    func(u *User)  u=%v \n", userPtr)
		}
	}

	fmt.Println()
	user := User{1, "no-modify", 25}
	userType := reflect.TypeOf(user)
	for i := 0; i < userType.NumMethod(); i++ {
		m := userType.Method(i)
		fmt.Printf("%v: %v\n", m, m.IsExported())
	}

}

测试结果

{TestUserNoPtr  func(*main_test.User, string) <func(*main_test.User, string) Value> 0}: true
{TestUserPtr  func(*main_test.User, string) <func(*main_test.User, string) Value> 1}: true
struct(*user)    func(u User)  u=&{1 no-modify 25} 
struct(*user)    func(u *User)  u=&{1 modify 25} 

{TestUserNoPtr  func(main_test.User, string) <func(main_test.User, string) Value> 0}: true

反射出来的,结构体指针可以调用那两个函数,而且是否修改也和receiver是否是指针有关,但是结构体就不能调用receiver是指针的,因为它只有一个函数。

3.嵌套结构体函数的分析

        测试代码1

//注意*User是指针
type UserChild struct {
	*User
	Id   int
	Name string
	Age  int
}

func TestReflectStruct(t *testing.T) {
	userOnePtr := &UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userOnePtr.TestUserNoPtr("modify")
	fmt.Printf("struct(*UserChild) fileld(*User)   func(u User)  u=%v \n", userOnePtr.User)

	userTwoPtr := &UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userTwoPtr.TestUserPtr("modify")
	fmt.Printf("struct(*UserChild) fileld(*User)   func(u *User)  u=%v\n", userTwoPtr.User)

	userOne := UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userOne.TestUserNoPtr("modify")
	fmt.Printf("struct(UserChild) fileld(*User)   func(u User)  u=%v\n", userOne.User)

	userTwo := UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userTwo.TestUserPtr("modify")
	fmt.Printf("struct(UserChild)  fileld(*User)  func(u *User)  u=%v\n", userTwo.User)
}

结果1

struct(*UserChild) fileld(*User)   func(u User)  u=&{1 no-modify 25} 
struct(*UserChild) fileld(*User)   func(u *User)  u=&{1 modify 25}
struct(UserChild) fileld(*User)   func(u User)  u=&{1 no-modify 25}
struct(UserChild)  fileld(*User)  func(u *User)  u=&{1 modify 25}

这个结果和第一个标题的结果一样,如果我们将*user,换成user,就是嵌入结构体不用指针

type UserChild struct {
	User
	Id   int
	Name string
	Age  int
}

func TestReflectStruct(t *testing.T) {
	userOnePtr := &UserChild{User{1, "no-modify", 25}, 1, "no-modify", 25}
	userOnePtr.TestUserNoPtr("modify")
	fmt.Printf("struct(*UserChild) fileld(User)   func(u User)  u=%v \n", userOnePtr.User)

	userTwoPtr := &UserChild{User{1, "no-modify", 25}, 1, "no-modify", 25}
	userTwoPtr.TestUserPtr("modify")
	fmt.Printf("struct(*UserChild) fileld(User)   func(u *User)  u=%v\n", userTwoPtr.User)

	userOne := UserChild{User{1, "no-modify", 25}, 1, "no-modify", 25}
	userOne.TestUserNoPtr("modify")
	fmt.Printf("struct(UserChild) fileld(User)   func(u User)  u=%v\n", userOne.User)

	userTwo := UserChild{User{1, "no-modify", 25}, 1, "no-modify", 25}
	userTwo.TestUserPtr("modify")
	fmt.Printf("struct(UserChild)  fileld(User)  func(u *User)  u=%v\n", userTwo.User)
}
struct(*UserChild) fileld(User)   func(u User)  u={1 no-modify 25} 
struct(*UserChild) fileld(User)   func(u *User)  u={1 modify 25}
struct(UserChild) fileld(User)   func(u User)  u={1 no-modify 25}
struct(UserChild)  fileld(User)  func(u *User)  u={1 modify 25}

结果2和结果1一样,也就是说嵌入结果是否是指针,不影响底层函数,它只和receiver是否是指针才能修改

4.嵌入结构体的反射

      测试代码1

func TestReflectStruct(t *testing.T) {
	userPtr := &UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userPtrType := reflect.TypeOf(userPtr)
	userPtrValue := reflect.ValueOf(userPtr)
	for i := 0; i < userPtrType.NumMethod(); i++ {
		m := userPtrType.Method(i)
		fmt.Printf("%v: %v\n", m, m.IsExported())
	}

	if userPtrType.Implements(reflect.TypeOf((*IUser)(nil)).Elem()) {
		if f, ok := userPtrValue.Interface().(IUser); ok {
			f.TestUserNoPtr("modify")
			fmt.Printf("struct(*UserChild)  fileld(*User)  func(u User)  u=%v \n", userPtr.User)
			f.TestUserPtr("modify")
			fmt.Printf("struct(*UserChild)  fileld(*User)  func(u *User)  u=%v \n", userPtr.User)
		}
	}

	fmt.Println()
	user := UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userType := reflect.TypeOf(user)
	userValue := reflect.ValueOf(user)
	for i := 0; i < userType.NumMethod(); i++ {
		m := userType.Method(i)
		fmt.Printf("%v: %v\n", m, m.IsExported())
	}

	if userType.Implements(reflect.TypeOf((*IUser)(nil)).Elem()) {
		if f, ok := userValue.Interface().(IUser); ok {
			f.TestUserNoPtr("modify")
			fmt.Printf("struct(UserChild)  fileld(*User)  func(u User)  u=%v \n", user.User)
			f.TestUserPtr("modify")
			fmt.Printf("struct(UserChild)  fileld(*User)   func(u *User)  u=%v \n", user.User)
		}
	}
}

        结果1为

{TestUserNoPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 0}: true
{TestUserPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 1}: true
struct(*UserChild)  fileld(*User)  func(u User)  u=&{1 no-modify 25} 
struct(*UserChild)  fileld(*User)  func(u *User)  u=&{1 modify 25} 

{TestUserNoPtr  func(main_test.UserChild, string) <func(main_test.UserChild, string) Value> 0}: true
{TestUserPtr  func(main_test.UserChild, string) <func(main_test.UserChild, string) Value> 1}: true
struct(UserChild)  fileld(*User)  func(u User)  u=&{1 no-modify 25} 
struct(UserChild)  fileld(*User)   func(u *User)  u=&{1 modify 25} 

        如果我们将如果我们将*user,换成user,再看一下结果2

{TestUserNoPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 0}: true
{TestUserPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 1}: true
struct(*UserChild)  fileld(User)  func(u User)  u={1 no-modify 25} 
struct(*UserChild)  fileld(User)  func(u *User)  u={1 modify 25} 

{TestUserNoPtr  func(main_test.UserChild, string) <func(main_test.UserChild, string) Value> 0}: true

如果UserChild是指针,嵌入结构体是否是指针,都可以原始的指针来调用,

如果UserChild不是指针,user不是指针这按照原始来调用,因为只有一个函数,如果是*user是指针,则可以按照正常来调用。

总过反射来调用函数和直接通过结构体来调用函数,就是反射不能调用非指针的接口函数

5.结构体函数的覆盖

测试案例1

func (u User) TestUserNoPtr(name string) {
	fmt.Println("has execute User TestUserNoPtr")
	u.Name = name
}

func (u *User) TestUserPtr(name string) {
	fmt.Println("has execute User TestUserPtr")
	u.Name = name
}

//加入覆盖的函数
func (u *UserChild) TestUserNoPtr(name string) {
	fmt.Println("has execute UserChild TestUserNoPtr")
	u.Name = name
}

func (u *UserChild) TestUserPtr(name string) {
	fmt.Println("has execute UserChild TestUserPtr")
	u.Name = name
}

func TestReflectStruct(t *testing.T) {
	userOnePtr := &UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userOnePtr.TestUserNoPtr("modify")
	fmt.Printf("struct(*UserChild) fileld(*User)   func(u User)  u=%v  c=%v\n", userOnePtr.User, userOnePtr)

	userTwoPtr := &UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userTwoPtr.TestUserPtr("modify")
	fmt.Printf("struct(*UserChild) fileld(*User)   func(u *User)  u=%v  c=%v\n", userTwoPtr.User, userTwoPtr)

	userOne := UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userOne.TestUserNoPtr("modify")
	fmt.Printf("struct(UserChild) fileld(*User)   func(u User)  u=%v  c=%v\n", userOne.User, userOne)

	userTwo := UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userTwo.TestUserPtr("modify")
	fmt.Printf("struct(UserChild)  fileld(*User)  func(u *User)  u=%v  c=%v\n", userTwo.User, userTwo)
}

//测试结果
has execute UserChild TestUserNoPtr
struct(*UserChild) fileld(*User)   func(u User)  u=&{1 no-modify 25}  c=&{0xc000096100 1 modify 25}
has execute UserChild TestUserPtr
struct(*UserChild) fileld(*User)   func(u *User)  u=&{1 no-modify 25}  c=&{0xc000096140 1 modify 25}
has execute UserChild TestUserNoPtr
struct(UserChild) fileld(*User)   func(u User)  u=&{1 no-modify 25}  c={0xc000096180 1 modify 25}
has execute UserChild TestUserPtr
struct(UserChild)  fileld(*User)  func(u *User)  u=&{1 no-modify 25}  c={0xc0000961c0 1 modify 25}


func TestReflectStructFunc(t *testing.T) {
	userPtr := &UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userPtrType := reflect.TypeOf(userPtr)
	userPtrValue := reflect.ValueOf(userPtr)
	for i := 0; i < userPtrType.NumMethod(); i++ {
		m := userPtrType.Method(i)
		fmt.Printf("%v: %v\n", m, m.IsExported())
	}

	if userPtrType.Implements(reflect.TypeOf((*IUser)(nil)).Elem()) {
		if f, ok := userPtrValue.Interface().(IUser); ok {
			f.TestUserNoPtr("modify")
			fmt.Printf("struct(*UserChild)  fileld(*User)  func(u User)  u=%v c=%v\n", userPtr.User, userPtr)

			//这里的函数应该分开测,毕竟上面的可能已经改变,但是我们只观测执行函数的逻辑和覆盖的逻辑
			f.TestUserPtr("modify")
			fmt.Printf("struct(*UserChild)  fileld(*User)  func(u *User)  u=%v c=%v\n", userPtr.User, userPtr)
		}
	}

	fmt.Println()
	user := UserChild{&User{1, "no-modify", 25}, 1, "no-modify", 25}
	userType := reflect.TypeOf(user)
	userValue := reflect.ValueOf(user)
	for i := 0; i < userType.NumMethod(); i++ {
		m := userType.Method(i)
		fmt.Printf("%v: %v\n", m, m.IsExported())
	}

	if userType.Implements(reflect.TypeOf((*IUser)(nil)).Elem()) {
		if f, ok := userValue.Interface().(IUser); ok {
			f.TestUserNoPtr("modify")
			fmt.Printf("struct(UserChild)  fileld(*User)  func(u User)  u=%v c=%v\n", user.User, user)
			//这里的函数应该分开测,毕竟上面的可能已经改变,但是我们只观测执行函数的逻辑和覆盖的逻辑
			f.TestUserPtr("modify")
			fmt.Printf("struct(UserChild)  fileld(*User)   func(u *User)  u=%v c=%v\n", user.User, user)
		}
	}
}

//测试结果2
{TestUserNoPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 0}: true
{TestUserPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 1}: true
has execute UserChild TestUserNoPtr
struct(*UserChild)  fileld(*User)  func(u User)  u=&{1 no-modify 25} c=&{0xc0001de0e0 1 modify 25}
has execute UserChild TestUserPtr
struct(*UserChild)  fileld(*User)  func(u *User)  u=&{1 no-modify 25} c=&{0xc0001de0e0 1 modify 25}

//下面的直接没有方法,也验证了反射的不能调用指针的接口

测试结果2

//将上面的指针去掉
func (u UserChild) TestUserNoPtr(name string) {
	fmt.Println("has execute UserChild TestUserNoPtr")
	u.Name = name
}

func (u UserChild) TestUserPtr(name string) {
	fmt.Println("has execute UserChild TestUserPtr")
	u.Name = name
}

//测试结果
has execute UserChild TestUserNoPtr
struct(*UserChild) fileld(*User)   func(u User)  u=&{1 no-modify 25}  c=&{0xc00030a220 1 no-modify 25}
has execute UserChild TestUserPtr
struct(*UserChild) fileld(*User)   func(u *User)  u=&{1 no-modify 25}  c=&{0xc00030a260 1 no-modify 25}
has execute UserChild TestUserNoPtr
struct(UserChild) fileld(*User)   func(u User)  u=&{1 no-modify 25}  c={0xc00030a320 1 no-modify 25}
has execute UserChild TestUserPtr
struct(UserChild)  fileld(*User)  func(u *User)  u=&{1 no-modify 25}  c={0xc00030a360 1 no-modify 25}

//和上面一样,用反射测
{TestUserNoPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 0}: true
{TestUserPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 1}: true
has execute UserChild TestUserNoPtr
struct(*UserChild)  fileld(*User)  func(u User)  u=&{1 no-modify 25} c=&{0xc00008e100 1 no-modify 25}
has execute UserChild TestUserPtr
struct(*UserChild)  fileld(*User)  func(u *User)  u=&{1 no-modify 25} c=&{0xc00008e100 1 no-modify 25}

{TestUserNoPtr  func(main_test.UserChild, string) <func(main_test.UserChild, string) Value> 0}: true
{TestUserPtr  func(main_test.UserChild, string) <func(main_test.UserChild, string) Value> 1}: true
has execute UserChild TestUserNoPtr
struct(UserChild)  fileld(*User)  func(u User)  u=&{1 no-modify 25} c={0xc00008e1a0 1 no-modify 25}
has execute UserChild TestUserPtr
struct(UserChild)  fileld(*User)   func(u *User)  u=&{1 no-modify 25} c={0xc00008e1a0 1 no-modify 25}

测试结果3

func (u *User) TestUserPtr(name string) {
	fmt.Println("has execute User TestUserPtr")
	u.Name = name
}

func (u *UserChild) TestUserNoPtr(name string) {
	fmt.Println("has execute UserChild TestUserNoPtr")
	u.Name = name
}

//将改为非指针
type UserChild struct {
	User
	Id   int
	Name string
	Age  int
}

func TestReflectStruct(t *testing.T) {
	userOnePtr := &UserChild{User{1, "no-modify", 25}, 1, "no-modify", 25}
	userOnePtr.TestUserNoPtr("modify")
	fmt.Printf("struct(*UserChild) fileld(User)   func(u User)  u=%v  c=%v\n", userOnePtr.User, userOnePtr)

	userTwoPtr := &UserChild{User{1, "no-modify", 25}, 1, "no-modify", 25}
	userTwoPtr.TestUserPtr("modify")
	fmt.Printf("struct(*UserChild) fileld(User)   func(u *User)  u=%v  c=%v\n", userTwoPtr.User, userTwoPtr)

	userOne := UserChild{User{1, "no-modify", 25}, 1, "no-modify", 25}
	userOne.TestUserNoPtr("modify")
	fmt.Printf("struct(UserChild) fileld(User)   func(u User)  u=%v  c=%v\n", userOne.User, userOne)

	userTwo := UserChild{User{1, "no-modify", 25}, 1, "no-modify", 25}
	userTwo.TestUserPtr("modify")
	fmt.Printf("struct(UserChild)  fileld(User)  func(u *User)  u=%v  c=%v\n", userTwo.User, userTwo)
}

//测试结果
has execute UserChild TestUserNoPtr
struct(*UserChild) fileld(User)   func(u User)  u={1 no-modify 25}  c=&{{1 no-modify 25} 1 modify 25}
has execute UserChild TestUserPtr
struct(*UserChild) fileld(User)   func(u *User)  u={1 no-modify 25}  c=&{{1 no-modify 25} 1 modify 25}
has execute UserChild TestUserNoPtr
struct(UserChild) fileld(User)   func(u User)  u={1 no-modify 25}  c={{1 no-modify 25} 1 modify 25}
has execute UserChild TestUserPtr
struct(UserChild)  fileld(User)  func(u *User)  u={1 no-modify 25}  c={{1 no-modify 25} 1 modify 25}

//和上面一样,用反射测
{TestUserNoPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 0}: true
{TestUserPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 1}: true
has execute UserChild TestUserNoPtr
struct(*UserChild)  fileld(User)  func(u User)  u={1 no-modify 25} c=&{{1 no-modify 25} 1 modify 25}
has execute UserChild TestUserPtr
struct(*UserChild)  fileld(User)  func(u *User)  u={1 no-modify 25} c=&{{1 no-modify 25} 1 modify 25}

测试结果4

//将测试3的改为
func (u UserChild) TestUserNoPtr(name string) {
	fmt.Println("has execute UserChild TestUserNoPtr")
	u.Name = name
}

func (u UserChild) TestUserPtr(name string) {
	fmt.Println("has execute UserChild TestUserPtr")
	u.Name = name
}

//测试结果为
has execute UserChild TestUserNoPtr
struct(*UserChild) fileld(User)   func(u User)  u={1 no-modify 25}  c=&{{1 no-modify 25} 1 no-modify 25}
has execute UserChild TestUserPtr
struct(*UserChild) fileld(User)   func(u *User)  u={1 no-modify 25}  c=&{{1 no-modify 25} 1 no-modify 25}
has execute UserChild TestUserNoPtr
struct(UserChild) fileld(User)   func(u User)  u={1 no-modify 25}  c={{1 no-modify 25} 1 no-modify 25}
has execute UserChild TestUserPtr
struct(UserChild)  fileld(User)  func(u *User)  u={1 no-modify 25}  c={{1 no-modify 25} 1 no-modify 25}

//和上面一样,用反射测
{TestUserNoPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 0}: true
{TestUserPtr  func(*main_test.UserChild, string) <func(*main_test.UserChild, string) Value> 1}: true
has execute UserChild TestUserNoPtr
struct(*UserChild)  fileld(User)  func(u User)  u={1 no-modify 25} c=&{{1 no-modify 25} 1 no-modify 25}
has execute UserChild TestUserPtr
struct(*UserChild)  fileld(User)  func(u *User)  u={1 no-modify 25} c=&{{1 no-modify 25} 1 no-modify 25}

{TestUserNoPtr  func(main_test.UserChild, string) <func(main_test.UserChild, string) Value> 0}: true
{TestUserPtr  func(main_test.UserChild, string) <func(main_test.UserChild, string) Value> 1}: true
has execute UserChild TestUserNoPtr
struct(UserChild)  fileld(User)  func(u User)  u={1 no-modify 25} c={{1 no-modify 25} 1 no-modify 25}
has execute UserChild TestUserPtr
struct(UserChild)  fileld(User)   func(u *User)  u={1 no-modify 25} c={{1 no-modify 25} 1 no-modify 25}

通过上面的测试,没得到有用的信息,有些人可能会自以为的

func (u *UserChild) TestUserNoPtr(name string) {
func (u User) TestUserNoPtr(name string) 

对于UserChild来说,上面的两个函数,指针的调用上面的接口,非指针调用下面的接口,即函数名相同就覆盖,和receiver的是否指针没有关系,和上面测的user是一样的,是否修改只看receiver是否指针有关,和嵌入结构体是否指针无关,最后反射出来的和实际的结构体调用是有区别的,结构体反射出来的,不能调用receiver是指针的函数,切记!!!!

2.结构体反射的实际应用

1.map ->struct的转换

        在实际的应用中,网络二进制[]byte进行传输,比如将json格式,probuf格式,binary库的write函数的1字节对齐的格式等等,还有gorm其他的将struct转换对应自己能分析的数据,都要用到反射。对于map到struct的函数转换,我们首先第一想到的就是深搜,因为上面的基本上的应用都是深搜的解决办法,因为struct能嵌套结构体,本身slice能嵌套slice,map也是,也可以互相嵌套,所以对于生成struct,slice,map我们就写一个生成函数,递归调用自己,其他基础类型,直接赋值,作为退出的条件,这就是map->struct的思想

func PraseStruct(m map[string]any, t reflect.Type, value reflect.Value) {
	for i := 0; i < t.NumField(); i++ {
		//value.Field(i).SetInt(int64(i + 1))
		//去掉多余的指针,这个要自己new数据,多级指针的话
		//structFiled := t.Field(i)
		//filedTag := structFiled.Tag
		//filedType := structFiled.Type
		//filedValue := value.Field(i)
		//
		//finalType := filedType
		//finalValue := filedValue
		//for finalValue.Kind() == reflect.Ptr {
		//	finalValue = finalValue.Elem()
		//
		//}
		//finalType = finalValue.Type()

		structFiled := t.Field(i)
		filedTag := structFiled.Tag
		filedType := structFiled.Type
		filedValue := value.Field(i)

		finalType := filedType
		//finalValue := filedValue
		for finalType.Kind() == reflect.Ptr {
			finalType = finalType.Elem()
		}

		if filedType.Kind() == reflect.Ptr && filedValue.Kind() == reflect.Ptr { //反向赋值
			middle := reflect.New(finalType).Elem()

			middleType := filedType
			for middleType.Kind() == reflect.Ptr {
				p := reflect.New(middle.Type())
				p.Elem().Set(middle)

				middle = p
				middleType = middleType.Elem()
			}

			filedValue.Set(middle)
		}

		finalValue := filedValue
		for finalValue.Kind() == reflect.Ptr {
			finalValue = finalValue.Elem()
		}

		switch finalValue.Kind() {
		case reflect.Struct:
			{
				tagName, ok := filedTag.Lookup("cesi")
				if !ok { //判断 omitemoty,required的规则

					return
				}

				v, okv := m[tagName]
				if !okv { //判断default的规则

					return
				}

				if structFiled.Anonymous { //是否是匿名结构体

				}
				PraseStruct(v.(map[string]interface{}), finalType, finalValue)
				//fmt.Println(finalType.Name())

				if finalType.Name() == "BaseData" {
					//两个成员函数不能带指针,如果有一个带,它只会有没有指针的成员函数,要注意
					//这里的finalType=reflect.Typeof(BaseData)
					//for i := 0; i < finalType.NumMethod(); i++ {
					//	m := finalType.Method(i)
					//	finalType.Method(i)
					//
					//	fmt.Printf("%v,%v\n", m, m.IsExported())
					//}
					//
					//if finalType.Implements(reflect.TypeOf((*BaseDataName)(nil)).Elem()) {//如果两个有一个带指针,这里就不会判断正确
					//	f, ok := finalValue.Interface().(BaseDataName) //如果两个有一个带指针,这里就不会ok
					//	if ok {
					//		f.PtrPrefixName()
					//	}
					//}

					//这里的finalType=reflect.Typeof(*BaseData),指针都可以调用
					ptrValue := reflect.New(finalType)
					ptrType := ptrValue.Type()
					for i := 0; i < ptrType.NumMethod(); i++ {
						m := ptrType.Method(i)
						ptrType.Method(i)

						fmt.Printf("%v,%v\n", m, m.IsExported())
					}

					if ptrType.Implements(reflect.TypeOf((*BaseDataName)(nil)).Elem()) { //如果两个有一个带指针,这里就不会判断正确
						f, ok := ptrValue.Interface().(BaseDataName) //如果两个有一个带指针,这里就不会ok
						if ok {
							f.PtrPrefixName()
						}
					}

				}

			}
		case reflect.Bool:
			{
				tagName, ok := filedTag.Lookup("cesi")
				if !ok { //判断 omitemoty,required的规则

					return
				}

				v, okv := m[tagName]
				if !okv { //判断default的规则

					return
				}

				if _, okb := v.(bool); !okb { //的类型不一致
					return
				}

				if !finalValue.CanSet() {
					return
				}
				finalValue.SetBool(v.(bool))
			}
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			{
				tagName, ok := filedTag.Lookup("cesi")
				if !ok { //判断 omitemoty,required的规则

					return
				}

				v, okv := m[tagName]
				if !okv { //判断default的规则

					return
				}

				vValue := reflect.ValueOf(v)
				if vValue.Kind() != reflect.Int && vValue.Kind() != reflect.Int8 &&
					vValue.Kind() != reflect.Int16 && vValue.Kind() != reflect.Int32 &&
					vValue.Kind() != reflect.Int64 { //的类型不一致
					return
				}

				if !finalValue.CanSet() {
					return
				}

				switch vValue.Kind() {
				case reflect.Int8:
					finalValue.SetInt(int64(v.(int8)))
				case reflect.Int16:
					finalValue.SetInt(int64(v.(int16)))
				case reflect.Int32:
					finalValue.SetInt(int64(v.(int32)))
				case reflect.Int64:
					finalValue.SetInt(v.(int64))
				default:
					fmt.Println("no unkown type")
				}
			}
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			{
				tagName, ok := filedTag.Lookup("cesi")
				if !ok { //判断 omitemoty,required的规则

					return
				}

				v, okv := m[tagName]
				if !okv { //判断default的规则

					return
				}

				//vValue := reflect.ValueOf(v)
				//if vValue.Kind() != reflect.Uint && vValue.Kind() != reflect.Uint8 &&
				//	vValue.Kind() != reflect.Uint16 && vValue.Kind() != reflect.Uint32 &&
				//	vValue.Kind() != reflect.Uint64 { //的类型不一致
				//	return
				//}
				//
				//switch vValue.Kind() {
				//case reflect.Uint8:
				//	finalValue.SetUint(uint64(v.(uint8)))
				//case reflect.Uint16:
				//	finalValue.SetUint(uint64(v.(uint16)))
				//case reflect.Uint32:
				//	finalValue.SetUint(uint64(v.(uint32)))
				//case reflect.Uint64:
				//	finalValue.SetUint(v.(uint64))
				//default:
				//	fmt.Println("no unkown type")
				//}

				if !finalValue.CanSet() {
					return
				}

				switch data := v.(type) {
				case uint8:
					finalValue.SetUint(uint64(data))
				case uint16:
					finalValue.SetUint(uint64(data))
				case uint32:
					finalValue.SetUint(uint64(data))
				case uint64:
					finalValue.SetUint(data)
				default:
					fmt.Println("no unkown type")
				}
			}
		case reflect.Float32, reflect.Float64:
			{
				tagName, ok := filedTag.Lookup("cesi")
				if !ok { //判断 omitemoty,required的规则
					return
				}

				v, okv := m[tagName]
				if !okv { //判断default的规则

					return
				}

				vValue := reflect.ValueOf(v)
				if vValue.Kind() != reflect.Float32 && vValue.Kind() != reflect.Float64 { //的类型不一致
					return
				}

				if !finalValue.CanSet() {
					return
				}

				if vValue.Kind() == reflect.Float32 {
					finalValue.SetFloat(float64(v.(float32)))
				} else {
					finalValue.SetFloat(v.(float64))
				}
			}
		case reflect.String:
			{
				tagName, ok := filedTag.Lookup("cesi")
				if !ok { //判断 omitemoty,required的规则

					return
				}

				v, okv := m[tagName]
				if !okv { //判断default的规则
					return
				}

				if !finalValue.CanSet() {
					return
				}
				switch data := v.(type) {
				case string:
					finalValue.SetString(data)
				case []byte:
					finalValue.SetString(string(data))
				default:
					fmt.Println("no unkown type")
				}
			}
		case reflect.Slice:
			{

				tagName, ok := filedTag.Lookup("cesi")
				if !ok { //判断 omitemoty,required的规则

					return
				}

				v, okv := m[tagName]
				if !okv { //判断default的规则
					return
				}

				vValue := reflect.ValueOf(v)
				if vValue.Kind() != reflect.Slice {
					return
				}

				if vValue.IsNil() { //map里的slice为空
					return
				}

				if !finalValue.CanSet() {
					return
				}

				targetValue, err := GenerateSlice(finalType, vValue)
				if err != nil {
					return
				}
				finalValue.Set(targetValue)
			}
		case reflect.Map:
			tagName, ok := filedTag.Lookup("cesi")
			if !ok { //判断 omitemoty,required的规则

				return
			}

			v, okv := m[tagName]
			if !okv { //判断default的规则
				return
			}

			vValue := reflect.ValueOf(v)
			if vValue.Kind() != reflect.Map {
				return
			}

			targetValue, err := GenerateMap(filedType.Key(), filedType.Elem(), vValue)
			if err != nil {
				return
			}
			if !finalValue.CanSet() {
				return
			}

			if !targetValue.Type().AssignableTo(finalValue.Type()) {
				return
			}
			finalValue.Set(targetValue)
		}

	}
}

func GenerateSlice(sliceType reflect.Type, mapSlice reflect.Value) (reflect.Value, error) {
	newSlice := reflect.MakeSlice(sliceType, mapSlice.Len(), mapSlice.Cap())
	if mapSlice.Len() == 0 {
		return newSlice, nil
	}

	baseElem := sliceType.Elem()

	endElem := baseElem
	for endElem.Kind() == reflect.Ptr {
		endElem = endElem.Elem()
	}
	//一个一个元素赋值
	for i := 0; i < mapSlice.Len(); i++ {
		elemValue := newSlice.Index(i)
		mapElemValue := mapSlice.Index(i)

		switch endElem.Kind() {
		case reflect.Struct:
			{
				v, ok := mapElemValue.Interface().(map[string]any)
				if !ok {
					return reflect.ValueOf(struct{}{}), errors.New("mapElemValue.Interface().(map[string]any)")
				}

				newStruct := reflect.New(endElem)
				endValue := newStruct
				for endValue.Kind() == reflect.Ptr {
					endValue = endValue.Elem()
				}
				PraseStruct(v, endValue.Type(), endValue)

				//[]***elem的struct的多级指针
				middleValue := newStruct.Elem()
				if baseElem.Kind() == reflect.Ptr {

					middleType := baseElem
					for middleType.Kind() == reflect.Ptr {
						p := reflect.New(middleValue.Type())
						p.Elem().Set(middleValue)
						middleValue = p

						middleType = middleType.Elem()
					}
				}

				elemValue.Set(middleValue)
			}
		case reflect.Slice:
			{
				fmt.Println(endElem, mapElemValue.Type())
				target, err := GenerateSlice(endElem, mapElemValue)
				if err != nil {
					return reflect.ValueOf(struct{}{}), err
				}
				elemValue.Set(target)
			}
		case reflect.Map:
			{
				v, ok := mapElemValue.Interface().(map[string]any)
				if !ok {
					return reflect.ValueOf(struct{}{}), errors.New("mapElemValue.Interface().(map[string]any)")
				}

				target, err := GenerateMap(endElem.Key(), endElem.Elem(), reflect.ValueOf(v)) //不能用keyValue直接赋值,因为它是any,kind是接口类型
				if err != nil {
					return reflect.ValueOf(struct{}{}), err
				}

				elemValue.Set(target)
			}
		default:
			{
				//常规类型的多级指针,真正的赋值
				startElemType := elemValue.Type()
				baseElemType := startElemType
				for baseElemType.Kind() == reflect.Ptr {
					baseElemType = baseElemType.Elem()
				}

				if startElemType.Kind() == reflect.Ptr {
					middleElem := reflect.New(baseElemType).Elem()

					middleType := startElemType
					for middleType.Kind() == reflect.Ptr {
						p := reflect.New(middleElem.Type())
						p.Elem().Set(middleElem)

						middleElem = p
						middleType = middleType.Elem()
					}

					elemValue.Set(middleElem)
				}

				endValue := elemValue
				for endValue.Kind() == reflect.Ptr {
					endValue = endValue.Elem()
				}

				switch data := mapElemValue.Interface().(type) {
				case bool, string, uint8, uint16, uint32, uint64, uint, int, int8, int32, int64, float32, float64:
					{
						realValue := reflect.ValueOf(data)
						if realValue.Kind() != endValue.Kind() {
							return reflect.ValueOf(struct{}{}), errors.New("realValue.Kind() != endValue.Kind()")
						}

						endValue.Set(realValue)
					}
				default:
					{
						//这里只能具体类型赋值具体类型,如果要any赋值到具体类型,必须和struct一样,每个元素要中断
						if !endValue.Type().AssignableTo(mapElemValue.Type()) {
							return reflect.ValueOf(struct{}{}), errors.New("endValue.Type().AssignableTo(mapElemValue.Type())")
						}

						endValue.Set(mapElemValue)
					}
				}

			}
		}

	}

	return newSlice, nil
}

func GenerateMap(keyType, elemType reflect.Type, mapValue reflect.Value) (reflect.Value, error) {
	generateMapType := reflect.MapOf(keyType, elemType)

	mapType := mapValue.Type()
	if generateMapType == mapType {
		return mapValue, nil
	}

	//map的key的type要相等
	if keyType != mapType.Key() {
		return reflect.ValueOf(struct{}{}), errors.New("key type is not queal")
	}

	target := reflect.MakeMapWithSize(generateMapType, mapValue.Len())

	endMapElem := elemType
	for endMapElem.Kind() == reflect.Ptr {
		endMapElem = endMapElem.Elem()
	}

	for _, key := range mapValue.MapKeys() {
		keyValue := mapValue.MapIndex(key)
		keyValueVV := keyValue.Interface()
		switch endMapElem.Kind() {
		case reflect.Slice:
			{
				targetElem, err := GenerateSlice(endMapElem, keyValue)
				if err != nil {
					return reflect.ValueOf(struct{}{}), err
				}
				target.SetMapIndex(key, targetElem)
			}
		case reflect.Struct:
			{
				v, ok := keyValue.Interface().(map[string]any)
				if !ok {
					return reflect.ValueOf(struct{}{}), errors.New("mapValue.Interface().(map[string]any)")
				}

				newStruct := reflect.New(endMapElem)
				endValue := newStruct
				for endValue.Kind() == reflect.Ptr {
					endValue = endValue.Elem()
				}
				PraseStruct(v, endValue.Type(), endValue)

				middleValue := newStruct.Elem()
				if elemType.Kind() == reflect.Ptr {

					middleType := elemType
					for middleType.Kind() == reflect.Ptr {
						p := reflect.New(middleValue.Type())
						p.Elem().Set(middleValue)
						middleValue = p

						middleType = middleType.Elem()
					}
				}

				target.SetMapIndex(key, middleValue)
			}
		case reflect.Map:
			{
				v, ok := keyValue.Interface().(map[string]any)
				if !ok {
					return reflect.ValueOf(struct{}{}), errors.New("mapValue.Interface().(map[string]any)")
				}

				targetElem, err := GenerateMap(endMapElem.Key(), endMapElem.Elem(), reflect.ValueOf(v)) //不能用keyValue直接赋值,因为它是any,kind是接口类型
				if err != nil {
					return reflect.ValueOf(struct{}{}), err
				}

				target.SetMapIndex(key, targetElem)
			}
		default:
			{
				switch data := keyValueVV.(type) {
				case bool, string, uint8, uint16, uint32, uint64, uint, int, int8, int32, int64, float32, float64:
					{
						realValue := reflect.ValueOf(data)
						if endMapElem.Kind() != realValue.Kind() {
							return reflect.ValueOf(struct{}{}), errors.New("endMapElem.Kind()!=realValue.Kind()")
						}

						target.SetMapIndex(key, realValue)
					}
				default: //any -> any
					{
						if !keyValue.Type().AssignableTo(endMapElem) {
							return reflect.ValueOf(struct{}{}), errors.New("!keyValue.Type().AssignableTo(endMapElem)")
						}

						target.SetMapIndex(key, keyValue)
					}
				}
			}
		}
	}

	return target, nil
}

func MarshalStruct(m map[string]any, v any) {
	if v == nil {
		fmt.Errorf("var s struct is not pointer")
	}
	//去掉多余的指针
	structType := reflect.TypeOf(v)
	structValue := reflect.ValueOf(v)

	finalType := structType
	finalValue := structValue
	for finalValue.Kind() == reflect.Ptr {
		finalValue = finalValue.Elem()
	}

	finalType = finalValue.Type()
	if finalValue.Kind() == reflect.Struct {
		PraseStruct(m, finalType, finalValue)
	}

	//打印
	//printValue := structValue
	//for printValue.Kind() == reflect.Ptr {
	//	printValue = printValue.Elem()
	//	fmt.Println(printValue)
	//}
}

type BaseData struct {
	Bool bool `cesi:"Bool"`

	Int8  int8    `cesi:"Int8"`
	Int16 int16   `cesi:"Int16"`
	Int32 int32   `cesi:"Int32"`
	Int64 **int64 `cesi:"Int64"`

	UInt8  uint8  `cesi:"UInt8"`
	UInt16 uint16 `cesi:"UInt16"`
	UInt32 uint32 `cesi:"UInt32"`
	UInt64 uint64 `cesi:"UInt64"`

	Float32 **float32 `cesi:"Float32"`
	Float64 float64   `cesi:"Float64"`
}

type BaseDataName interface {
	PtrPrefixName()
	PrefixName()
}

func (b *BaseData) PtrPrefixName() {
	fmt.Println("b*BaseData")
	b.Int32 = 99999
}

func (b BaseData) PrefixName() {
	fmt.Println("b*BaseData")
	b.Int32 = 99999
}

type MiddleData struct {
	RealBaseData *BaseData                   `cesi:"RealBaseData"`
	String       string                      `cesi:"String"`
	SliceByte    **[]**string                `cesi:"SliceByte"`
	SliceAny     []string                    `cesi:"SliceAny"` /*  **string   any*/
	SliceStruct  []***BaseData               `cesi:"SliceStruct"`
	SliceSlice   [][]**int                   `cesi:"SliceSlice"`
	SliceMap     []map[string]int            `cesi:"SliceMap"`
	Map          map[string]int              `cesi:"Map"`
	MapAny       map[string]int              `cesi:"MapAny"`
	MapStruct    map[string]***BaseData      `cesi:"MapStruct"`
	MapMap       map[string]map[string]int32 `cesi:"MapMap"`
	MapSlice     map[string][]string         `cesi:"MapSlice"`
}

type StructData struct {
	//BaseData
	RealMiddleData ***MiddleData `cesi:"MiddleData"`

	//Bool bool `cesi:"Bool"`
	//Int8  int8  `cesi:"Int8"`
	//Int16 int16 `cesi:"Int16"`
	//Int32 int32 `cesi:"Int32"`
	//Int64 int64 `cesi:"Int64"`
	//
	//UInt8  int8  `cesi:"UInt8"`
	//UInt16 int16 `cesi:"UInt16"`
	//UInt32 int32 `cesi:"UInt32"`
	//UInt64 int64 `cesi:"UInt64"`
	//
	//Float32 float32 `cesi:"Float32"`
	//Float64 float64 `cesi:"Float64"`

}

func TestReflectStructPtr(t *testing.T) {

	mBaseData := map[string]interface{}{
		"Bool": true,

		"Int8":  int8(-1),
		"Int16": int16(-2),
		"Int32": int32(-3),
		"Int64": int64(-4),

		"UInt8":  uint8(1),
		"UInt16": uint16(2),
		"UInt32": uint32(3),
		"UInt64": uint64(4),

		"Float32": float32(1.99),
		"Float64": float64(2.9999),
	}

	mm := map[string]interface{}{
		"RealBaseData": mBaseData,
		"String":       []byte("abcd"),
		"SliceByte":    []string{"123", "456", "789"},
		"SliceAny":     []any{"123", "456", "789"},
		"SliceStruct": []map[string]any{
			{"Bool": true,

				"Int8":  int8(-1),
				"Int16": int16(-2),
				"Int32": int32(-3),
				"Int64": int64(-4),

				"UInt8":  uint8(1),
				"UInt16": uint16(2),
				"UInt32": uint32(3),
				"UInt64": uint64(4),

				"Float32": float32(1.99),
				"Float64": float64(2.9999),
			},
		},
		"SliceSlice": [][]any{
			{1, 23, 4},
			{2, 4, 5},
		},

		"SliceMap": []map[string]any{
			{
				"1": 1,
				"2": 2,
			},
			{
				"11": 11,
				"22": 22,
			},
		},
		"Map": map[string]int{
			"1": 1,
			"2": 2,
		},
		"MapAny": map[string]any{
			"1": 1,
			"2": 2,
		},
		"MapStruct": map[string]any{
			"BaseData": map[string]any{
				"Bool": true,

				"Int8":  int8(-1),
				"Int16": int16(-2),
				"Int32": int32(-3),
				"Int64": int64(-4),

				"UInt8":  uint8(1),
				"UInt16": uint16(2),
				"UInt32": uint32(3),
				"UInt64": uint64(4),

				"Float32": float32(1.99),
				"Float64": float64(2.9999),
			},
		},
		"MapMap": map[string]any{
			"BaseData": map[string]any{
				"Int32":  int32(-3),
				"UInt32": int32(3),
			},
			"BaseData1": map[string]any{
				"Int32":  int32(-4),
				"UInt32": int32(4),
			},
		},
		"MapSlice": map[string][]string{
			"1": {"11", "22", "33"},
			"2": {"2", "22", "33"},
		},
	}

	ms := map[string]interface{}{
		"MiddleData": mm,
	}

	//var st *StructData  //这种不行,st==nil

	// st := new(StructData) //一级指针

	//sst := new(StructData) //二级指针
	//st := &sst

	//Int64 := int64(0)
	//IInt64 := &Int64
	//
	//Float32 := float32(0.0)
	//FFloat32 := &Float32
	//
	//bd := new(BaseData)
	//bd.Int64 = &IInt64
	//bd.Float32 = &FFloat32
	//bbd := &bd
	//
	//md := new(MiddleData)
	//md.RealBaseData = bbd
	//
	//mmd := &md

	ssst := new(StructData) //三级指针
	//ssst.RealBaseData = *bd

	//ssst.RealMiddleData = mmd

	sst := &ssst
	st := &sst

	MarshalStruct(ms, st)

	//fmt.Println(bd)
	fmt.Println("1")
}

     上面的是自己随手写的一个map->struct的demo,可能存在一些细节上的bug,但是上面的例子是可以运行的,写这个的目的是为了熟悉反射的用法,所以你在上面能看到各种方法,是不一样的。

        1.struct的fileld出来多级指针是可以canset的,因为直接给它赋值为flagsddr的,一般类型的多级指针是不行的

        2.any通过通过类型中断出具体的类型,才可能通过反射得出它的具体类型,否则就是any类型

        3.type的elem()的函数和value的函数elem的区别,是type的elem的函数,如果它是指针,指向的是指针指向的type,和value的差不多,如果是map和slice,是指向它元素的type,而value的elem只能有any和ptr的类型的值,any会怎么产生了,reflect.TypeOf((*BaseDataName)(nil)).Elem()

        4.对于***的多级指针,如果不想一个一个的new,就应该反射,一个一个的new,然后赋值

2.rpc的函数的序列化

        对于进程间的rpc函数我们一般是通过一个probuf的struct将所有的参数包裹起来成一个,但是我们可不可以传递多个参数了,答案是可以的,下面的代码是一个很简易的多个参数的写法,就是利用反射,记录函数类型的输入输出参数的类型,然后进行正反序列化

//probuf的结构体
type Ipacket struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Stx            int32   `protobuf:"varint,1,opt,name=Stx,proto3" json:"Stx,omitempty"`
	DestServerType SERVICE `protobuf:"varint,2,opt,name=DestServerType,proto3,enum=message.SERVICE" json:"DestServerType,omitempty"`
	Ckx            int32   `protobuf:"varint,3,opt,name=Ckx,proto3" json:"Ckx,omitempty"`
	Id             int64   `protobuf:"varint,4,opt,name=Id,proto3" json:"Id,omitempty"`
}

type C_A_LoginRequest struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	PacketHead  *Ipacket `protobuf:"bytes,1,opt,name=PacketHead,proto3" json:"PacketHead,omitempty"`
	AccountName string   `protobuf:"bytes,2,opt,name=AccountName,proto3" json:"AccountName,omitempty"`
	Password    string   `protobuf:"bytes,3,opt,name=Password,proto3" json:"Password,omitempty"`
	BuildNo     string   `protobuf:"bytes,5,opt,name=BuildNo,proto3" json:"BuildNo,omitempty"`
	Key         int64    `protobuf:"varint,6,opt,name=Key,proto3" json:"Key,omitempty"` //uint32 Crc = 7;
}


func RegisterFunc(ctx context.Context, a int, pst *User, packet *message.C_A_LoginRequest) {
	V := ctx.Value("funcname")
	fmt.Println("ctx:", V)

	fmt.Println("a:", a)

	fmt.Println("pst:", pst)

	fmt.Println("packet:", packet)
}

func SendFuncParams(b string, a int, pst *User, packet *message.C_A_LoginRequest) []byte {
	return MashalCesi(b, a, pst, packet)
}

func MashalCesi(funcname string, p ...interface{}) []byte {
	buffer := bytes.NewBuffer([]byte{})
	enData := gob.NewEncoder(buffer)
	enData.Encode(funcname)
	for _, v := range p {
		enData.Encode(v)
	}

	return buffer.Bytes()
}

func TestReflectRegisterFunc(t *testing.T) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Printf("=%s", err)
		}
	}()

	funcname := "RegisterFunc"

	funcType := reflect.TypeOf(RegisterFunc)

	funcVal := reflect.ValueOf(RegisterFunc)

	funcParams := reflect.TypeOf(RegisterFunc).String()

	fmt.Println("funcParams is ", funcParams)

	paramsNum := funcType.NumIn()

	paramsNums := make([]interface{}, paramsNum)

	user := &User{1, "Allen.Wu", 25}
	packet1 := &message.C_A_LoginRequest{PacketHead: message.BuildPacketHead(0, message.SERVICE_GATESERVER),
		AccountName: "lw", Password: "123456", BuildNo: "2", Key: 678}

	buffer := SendFuncParams(funcname, 1, user, packet1)

	buf := bytes.NewBuffer(buffer)
	deData := gob.NewDecoder(buf)

	for i := 0; i < paramsNum; i++ {
		if i == 0 {
			//val:=reflect.New(funcType.In(i)) //context.Context is not string

			val := reflect.New(reflect.TypeOf(string("")))
			deData.DecodeValue(val)
			//name:=val.Interface().(string) //interface {} is *string, not string

			name := val.Elem().Interface().(string)
			paramsNums[i] = context.WithValue(context.Background(), "funcname", name)
			continue
		}

		val := reflect.New(funcType.In(i))
		deData.DecodeValue(val)
		paramsNums[i] = val.Elem().Interface()

	}

	in := make([]reflect.Value, paramsNum)

	for i := 0; i < paramsNum; i++ {
		in[i] = reflect.ValueOf(paramsNums[i])
		fmt.Println("funcParams is ", in[i])
	}

	funcVal.Call(in)
}

         上面的代码可能不规范,但是目的是学习,没有用到mock的测试方法,

         由于测试,我们省略了socket的网络传输,毕竟只要是[]byte就可以传输了,通过上面的方法我们就可以实现自己的多参数的rpc传输了。其实做游戏的,可以实现自己的SendRpc(SrcActorID,DstActorID,FuncName,...params)rpc函数的这种形式,这都是题外话了。

        总结:反射还是很重要的知识,务必要好好掌握,最后,本人能力有限,希望大佬们多多提意见

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值