使用反射前,我们需要提前做好映射配置
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}