Go反射-通过反射调用结构体的方法(带入参)

使用反射前,我们需要提前做好映射配置

papckage_struct_relationship.go

go 复制代码
package reflectcommon

import (
	api "template/api"
)

// 包名到包对象的映射
var structMap = map[string]func() interface{}{
	"template/api": func() interface{} { return &api.User{} },   // 调用User结构体的方法
}

反射核心代码

go 复制代码
package reflectcommon

import (
	"fmt"
	"reflect"
	api "template/api"
)

/*
args []interface{},支持任意类型的参数
*/
func CallPackageStructMethod(pkgPath, methodName string, args []interface{}) ([]reflect.Value, *[]error) {
	fmt.Println(123123)
	errs := []error{}

	// 1. 获取构造函数
	constructor, ok := structMap[pkgPath]
	if !ok {
		errs = append(errs, fmt.Errorf("包 %s 未注册", pkgPath))
		return nil, &errs
	}

	// 2. 创建实例
	instance := constructor()
	instanceValue := reflect.ValueOf(instance)

	// 3. 检查是否为指针
	if instanceValue.Kind() != reflect.Ptr {
		errs = append(errs, fmt.Errorf("构造函数必须返回指针"))
		return nil, &errs
	}

	// 4. 获取指向的结构体值
	structValue := instanceValue.Elem()
	if structValue.Kind() != reflect.Struct {
		errs = append(errs, fmt.Errorf("预期结构体,实际得到 %s", structValue.Kind()))
		return nil, &errs
	}
	
	// 5. 获取方法
	method := instanceValue.MethodByName(methodName)
	if !method.IsValid() {
		errs = append(errs, fmt.Errorf("方法 %s 不存在", methodName))
		return nil, &errs
	}

	// 6. 准备参数
	var in []reflect.Value
	for _, arg := range args {
		in = append(in, reflect.ValueOf(arg))
	}

	// 7. 调用方法并返回结果
	results := method.Call(in)
	return results, nil
}

定义结构体方法

template/api/create_token.go

go 复制代码
package api

import (
	"fmt"
	"template/common"
	"template/types"
)

type User struct {
	UserId string
	Token  string
}

func newCreateTokenApiV1() *types.Api {
	apiV1 := types.Api{
		Host:        "",
		Prefix:      "",
		Version:     "/v1",
		Url:         "/token/create",
		Method:      "POST",
		ContentType: "application/json",
	}
	return &apiV1
}


func (user User) CreateTokenApi(user1 map[string]interface{}, userId, token string) (*types.Api, *types.Result, error) {
	// 处理请求URL
	data := map[string]interface{}{
		"userId": userId,
		"token":  token,
		"user":   user1,
	}
	fmt.Println("xxxxxxx---进来啦")
	apiV1 := newCreateTokenApiV1()
	apiV1.ReqData = data

	result := &types.Result{
		Header:   nil,
		Duration: 2,
		Resp: struct {
			Code      string      `json:"code"`
			Message   string      `json:"message"`
			RequestId string      `json:"requestId"`
			Response  interface{} `json:"response"`
		}{
			Code:      "000000",
			Message:   "success",
			RequestId: "123456",
			Response:  data,
		},
	}
	return apiV1, result, nil
}

调用

go 复制代码
package main

import (
	"template/common"
	reflectcommon "template/reflectCommon"
	"template/types"

	"github.com/douyu/jupiter/pkg/xlog"
)

func main() {
	// 这里的顺序主要要与调用发放的入参保持一致
	reqData := []interface{}{
		map[string]interface{}{"id": 1, "name": "test", "age": 18},
		"MyUserid",
		"MuToken",
	} }}
	results, errList := reflectcommon.CallPackageStructMethod("template/api", "CreateTokenApi", reqData)
	if errList != nil && len(*errList) > 0 {
		xlog.Error("CreateTokenApi failed", xlog.Any("error", errList))
		return
	}

	// 5. 解析返回结果 (api, result, error)
	if len(results) >= 3 {
		apiV1 := results[0].Interface().(*types.Api)
		result := results[1].Interface().(*types.Result)
		err := results[2].Interface() // 可能是nil

		xlog.Info("success",
			xlog.Any("api", apiV1),
			xlog.Any("result", result),
			xlog.Any("error", err))
	}

}

执行日志:

PS D:\project\go\src\template> go run .

123123

xxxxxxx---进来啦

1746258031 INFO default success {"api": {"name":"","prefix":"/efile","version":"/v1","url":"/token/create","fullUrl":"","method":"POST","reqHeader":null,"ContentType":"application/json","param":null,"reqData":{"token":"MuToken","user":{"age":18,"id":1,"name":"test"},"userId":"MyUserid"},"excuteUid":"","respContentType":""}, "result": {"header":null,"duration":2,"resp":{"code":"000000","message":"success","requestId":"123456","response":{"token":"MuToken","user":{"age":18,"id":1,"name":"test"},"userId":"MyUserid"}}}, "error": null}

相关推荐
2401_8919573126 分钟前
list的一些特性(C++)
开发语言·c++
二十雨辰35 分钟前
[尚庭公寓]07-Knife快速入门
java·开发语言·spring
Python大数据分析@37 分钟前
Origin、MATLAB、Python 用于科研作图,哪个最好?
开发语言·python·matlab
编程零零七1 小时前
Python巩固训练——第一天练习题
开发语言·python·python基础·python学习·python练习题
我爱Jack1 小时前
时间与空间复杂度详解:算法效率的度量衡
java·开发语言·算法
米饭「」1 小时前
C++AVL树
java·开发语言·c++
杂雾无尘2 小时前
开发者必看,全面解析应用更新策略,让用户无法拒绝你的应用更新!
ios·xcode·swift
心愿许得无限大2 小时前
Qt 常用界面组件
开发语言·c++·qt
2401_858286112 小时前
OS15.【Linux】gdb调试器的简单使用
linux·运维·服务器·开发语言·gdb
牛马baby2 小时前
MATLAB下载安装教程(附安装包)2025最新版(MATLAB R2024b)
开发语言·matlab