如何巧妙的利用go的反射通過(guò)一個(gè)接口調(diào)用不同函數(shù)

任何方法都是有利有弊,通過(guò)反射的方法可以實(shí)現(xiàn)一個(gè)接口調(diào)用多個(gè)不同的函數(shù),但是使用反射某種程度上也是犧牲了部分性能。

下面通過(guò)幾組代碼通過(guò)代碼中的注釋解釋其原理,通過(guò)只調(diào)用FunCall執(zhí)行不同的函數(shù)

一 定義執(zhí)行函數(shù)

// 入庫(kù)前的判斷不再贅述
/**
 *@Method db注冊(cè)方法
 *@Params userName,password string
 *@Return 返回執(zhí)行信息
 */
func Register(userName,password string)(res DBResult){
    user := UserModel{
        UserName: userName,
        Password: password,
    }
    // 查詢用戶是否已經(jīng)存在
    existed := user.userExisted()
    if existed {
        res.Suc = false
        res.Msg = "用戶名已存在,請(qǐng)重新輸入"
        return
    }
    // 不存在寫庫(kù)
    err := mysqldb.WmConn().Create(&user).Error
    if err != nil {
        res.Suc = false
        res.Msg = "注冊(cè)失敗,請(qǐng)重新嘗試"
        return
    }
    res.Suc=true
    res.Data=true
    return

}

func (user *UserModel)userExisted() bool {
    // 如果不存在found為true,存在為false
    found := mysqldb.RmConn().Where(`user_name = ?`,user.UserName).First(&user).RecordNotFound()
    if !found {
        return true
    }
    return false
}

二 定義方法map及方法解析函數(shù)

package mapper

import (
    "errors"
    "micro-file-store/service/dbproxy/orm"
    "reflect"
)

// 定義方法map
var funcs = map[string]interface{}{
    "/user/register":orm.Register,
}

/**
 *@Method 方法解析
 *@Params name:方法map中的key,params:方法所需要的參數(shù)
 *@Return 返回方法執(zhí)行結(jié)果slice和錯(cuò)誤
 */
func FuncCall(name string,params...interface{})(result []reflect.Value,err error){
    if _,ok := funcs[name];!ok{
        err = errors.New("請(qǐng)求路徑不存在")
        return
    }

    // 通過(guò)反射獲取方法內(nèi)存地址
    f := reflect.ValueOf(funcs[name])
    // 對(duì)比傳入?yún)?shù)的長(zhǎng)度是否與通過(guò)反射取出的方法需要的參數(shù)數(shù)量是否一致
    if len(params) != f.Type().NumIn(){
        err = errors.New("傳入?yún)?shù)與需要的參數(shù)數(shù)量不一致")
        return
    }
    // 創(chuàng)建一個(gè)切片用于放入?yún)?shù)
    in := make([]reflect.Value,len(params))
    // 初始化index
    var i = 0
    // 遍歷參數(shù)
    for k,param := range params{
        // 判斷應(yīng)位置的參數(shù)是否與需要的類型相同
        if reflect.TypeOf(param) != f.Type().In(i){
            err = errors.New("傳入?yún)?shù)類型與需要的不一致")
            return
        }
        // 如果相同加入in切片
        in[k] = reflect.ValueOf(param)
        i ++
    }

    // call將in參數(shù)傳給f方法并執(zhí)行,返回結(jié)果賦值給result,該方法會(huì)執(zhí)行f(in[0],in[1],...)
    result = f.Call(in)
    return
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容