使用反射前,我們需要提前做好映射配置
papckage_struct_relationship.go
package reflectcommonimport (api "template/api"
)// 包名到包對象的映射
var structMap = map[string]func() interface{}{"template/api": func() interface{} { return &api.User{} }, // 調用User結構體的方法
}
反射核心代碼
package reflectcommonimport ("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.Valuefor _, arg := range args {in = append(in, reflect.ValueOf(arg))}// 7. 調用方法并返回結果results := method.Call(in)return results, nil
}
定義結構體方法
template/api/create_token.go
package apiimport ("fmt""template/common""template/types"
)type User struct {UserId stringToken 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) {// 處理請求URLdata := map[string]interface{}{"userId": userId,"token": token,"user": user1,}fmt.Println("xxxxxxx---進來啦")apiV1 := newCreateTokenApiV1()apiV1.ReqData = dataresult := &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
}
調用
package mainimport ("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() // 可能是nilxlog.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}