Golang過載函式(反射模擬)
阿新 • • 發佈:2021-01-17
- 首先認清過載函式的定義
1:函式引數個數不同
2:函式引數型別不同,或者型別順序不同
Go語言本身不支援函式的過載,所以,我們利用反射+switch進行模擬反射,動態進行函式呼叫。
根據函式引數的個數不同,實現函式過載
首先宣告結構體,並繫結兩個引數
type Students struct {
Name string `json:"name"`
Age int
}
func (stu Students)T(n1 int,n2 int)int{//方法需要傳遞兩個引數
return n1+n2
}
func (stu Students) R(n1 int)int{//方法需要傳遞一個引數
return n1
}
實現動態呼叫方法的函式
func reflecttest(n interface{},n2 ...interface{})(int,error){
v:=reflect.ValueOf(n)
switch len(n2) {
case 1://如果傳參為一個值
params:=make([]reflect.Value,1)
params[0]=reflect.ValueOf(n2[0])//注意傳參時,需要將值的型別轉化為value型別
return int(v.MethodByName("R" ).Call(params)[0].Int()),nil//注意,返回的值以陣列形式進行返回,再將返回的值轉化為int64,再強制轉化為int型資料
case 2:如果引數為兩個
params:=make([]reflect.Value,2)
for k,v1:=range n2{
params[k]=reflect.ValueOf(v1)
}
return int(v.MethodByName("T").Call(params)[0].Int()),nil
default://如果傳參的數量不是一個或兩個。
err:=errors.New("呼叫函式不存在" )
return 0,err//返回錯誤
}
}
根據函式引數型別的不同,呼叫不同的函式
結構體及其繫結的方法
type Students struct {
Name string `json:"name"`
Age int
}
func (stu Students)T(n1 int,n2 int)string{
return n1+"T()"+strconv.Itoa(n2)
}
func (stu Students)R(n1 int,n2 string)string{
return strconv.Itoa(n1)+"R()"+n2
}
func reflecttest(n interface{},n2 ...interface{})(string,error){
v:=reflect.ValueOf(n)
if len(n2)!=2{//如果引數個數不為2,返回錯誤
err:=errors.New("引數個數錯誤")
return "",err
}
if reflect.TypeOf(n2[0]).String()!="int"{//如果第一個資料型別不為int型,返回錯誤
err:=errors.New("引數型別錯誤")
return "",err
}
switch n2[1].(type){//針對第二個引數的引數型別,進行討論
case string://如果為string
params:=make([]reflect.Value,2)
for k,v1:=range n2 {
params[k]=reflect.ValueOf(v1)
}
return v.MethodByName("R").Call(params)[0].String(),nil
case int://如果為int
params:=make([]reflect.Value,2)
for k,v1:=range n2{
params[k]=reflect.ValueOf(v1)
}
return v.MethodByName("T").Call(params)[0].String(),nil
default://如果不為string或int
err:=errors.New("未找到相應函式")
return "",err
}
}
型別順序不同,呼叫不同函式
結構體及其繫結的方法
type Students struct {
Name string `json:"name"`
Age int
}
func (stu Students)T(n1 string,n2 int)string{
return n1+"T()"+strconv.Itoa(n2)
}
func (stu Students)R(n1 int,n2 string)string{
return strconv.Itoa(n1)+"R()"+n2
}
func reflecttest(n interface{},n2 ...interface{})(string,error){
if len(n2)!=2{//判斷引數是否為2個
err:=errors.New("引數個數不正確")
return "",err
}
v:=reflect.ValueOf(n)
params:=make([]reflect.Value,2)
switch n2[0].(type) {
case string://判斷第一個引數的型別
if reflect.TypeOf(n2[1]).String()=="int"{//判斷第二個引數的型別
for k,v1:=range n2{
params[k]=reflect.ValueOf(v1)
}
return v.MethodByName("T").Call(params)[0].String(),nil
}else{
err:=errors.New("由於第二個引數型別錯誤,未能找到函式")
return "",err
}
case int://判斷第一個引數型別
if reflect.TypeOf(n2[1]).String()=="string"{//判斷第二個引數型別
for k,v1:=range n2{
params[k]=reflect.ValueOf(v1)
}
return v.MethodByName("R").Call(params)[0].String(),nil
}else{
err:=errors.New("第二個引數型別錯誤,函式呼叫失敗")
return "",err
}
default:
err:=errors.New("第一個引數型別錯誤,函式呼叫失敗")
return "",err
}
}