1. 程式人生 > 其它 >Golang過載函式(反射模擬)

Golang過載函式(反射模擬)

技術標籤:golangGO筆記golang反射

  • 首先認清過載函式的定義
    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://如果不為stringint
		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
	}
}