Exploring the functions of Go type parameters

Keywords: Programming Go

In go language, the definition of a function can be different from the caller of the function. In other words, the lack of runtime type security allows parameters at the call end of a function to be inconsistent with those at the definition end of the function. Go does not support the polymorphic nature of functions, which makes it impossible to define polymorphic functions based on the type or number of parameters. However, you can define polymorphic parameters. In the go build function, the append, close, delete, copy, cap and len functions all use parameter polymorphism.

In Go programming, sometimes in order to achieve the concise beauty of the code, we write some generalized functions. The use of these generalized functions is the Go reflection mechanism.

/**
The objective function model is:
func CallTypeFunc(f func(A) B, ps []A) []B
 */
 //Only support go release above 1.1
func CallTypeFunc(f interface{}, ps interface{}) interface{} {
    vf := reflect.ValueOf(f)
    vps := reflect.ValueOf(ps)

    // 3) Map's return type must be `[]B1` where `B == B1`.
    tys := reflect.SliceOf(vf.Type().Out(0))

    vys := reflect.MakeSlice(tys, vps.Len(), vps.Len())
    for i := 0; i < vps.Len(); i++ {
        y := vf.Call([]reflect.Value{vps.Index(i)})[0]
        vys.Index(i).Set(y)
    }
    return vys.Interface()
}

The input parameter of the first function is the same as that of the second parameter slice, and the return type of the parameter function is the same as that of the whole function, that is, the generalized model is func CallTypeFunc(f func(A) B, ps []A) []B.

Verify the function above, and see the following for the test code.

fmt.Printf(" CallTypeFunc(func(x string) int { return len(x) }, []string{\"1\", \"10\", \"100\"}).([]int) return :%+v",
    CallTypeFunc(func(x string) int { return len(x) }, []string{"1", "10", "100"}))

fmt.Printf(" CallTypeFunc(func(x int) int { return x*x }, []int{1, 10, 100}).([]int) return :%+v",
    CallTypeFunc(func(x int) int { return x*x }, []int{1, 10, 100}))

//Output results:
// CallTypeFunc(func(x string) int { return len(x) }, []string{"1", "10", "100"}).([]int) return :[1 2 3]
//CallTypeFunc(func(x int) int { return x*x }, []int{1, 10, 100}).([]int) return :[1 100 10000]

If you carefully analyze the above code, you will find that there is a bug in the parameter. There is no validation that the input parameter type conforms to the parameter definition of the function. In order to fix this problem, we need to add parameter validation logic.

Posted by proctk on Tue, 05 May 2020 11:04:33 -0700