调用泛型函数类型:无效操作:不能调用非函数 fn

Calling a generic function type: invalid operation: cannot call non-function fn

我将 post 我目前正在处理的代码示例。我收到错误:

error: invalid operation: cannot call non-function fn (variable of type MF constrained by MapFunc)

是否可以使用包含不同函数签名的约束以这种方式使用? (如果可能的话,我想了解如何让我写的东西首先发挥作用。)

示例如下:

package main

import "fmt"

// MapFunc constraint used in Funcy
type MapFunc interface {
    func(s string, ss []string) []string | func(s string, ss []string) []bool
}

// MapFuncType used for Funcy return constraint
type MapFuncType interface {
    string | bool
}

// Funcy preforms map operation on generic map functions
func Funcy[MF MapFunc, MFT MapFuncType](s string, ss []string, fn MF) []MFT {
    return fn(s, ss)
    // error: invalid operation: cannot call non-function fn (variable of type
    // MF constrained by MapFunc)
}

// appendTo adds given string to the end of each index of given slice of strings
// Ex. appendTo("_", []string{"append", "to"}) --> []string{"append_", "to_"}
func appendTo(s string, ss []string) []string {
    var slice []string
    for _, v := range ss {
        slice = append(slice, v+s)
    }
    return slice
}

// isMatch checks given string against each index in given string slice for a
// match
// Ex. isMatch("hi", []string{"hello", "hi"}) --> []bool{false, true}
func isMatch(s string, ss []string) []bool {
    var slice []bool
    for _, v := range ss {
        slice = append(slice, s == v)
    }
    return slice
}

func main() {
    slice1 := []string{"append", "to"}
    slice2 := []string{"hello", "hi"}

    fmt.Println(Funcy(slice1, appendTo))
    // want: []string{"append_", "to_"}
    // got: error: cannot infer MFT

    fmt.Println(Funcy(slice2, isMatch))
    //[]bool{false, true}
    // got: error: cannot infer MFT
}

当您将类型参数 MF 约束为 MapFunc 时,您无法调用 fn,因为 MapFunc 的类型集中的函数类型不有相同的签名。他们有不同的 return 类型 []string[]bool.

所以 fn 类型的变量实际上不支持被调用,你会得到(有点神秘的)错误消息“无法调用 non-function fn”。

更正式地说,只有 具有核心类型 类型函数的值才能被调用,但约束 MapFunc 没有核心类型。

解决方法是参数化 MapFunc 并将该类型参数用作 return 值,这样在实例化时,它就会有一个核心类型:

type MapFunc[T MapFuncType] interface {
    func(s string, ss []string) []T
}

并在Funcy中用MFT实例化约束:

func Funcy[MF MapFunc[MFT], MFT MapFuncType](s string, ss []string, fn MF) []MFT {
    return fn(s, ss)
}

游乐场:https://go.dev/play/p/q88aJLgnzXZ