在Golang中转换函数类型

4
// Each type have Error() string method.
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
//  type error interface {
//   Error() string
//  }

func (f binFunc) Error() string {
    return "binFunc error"
}

func func_type_convert() {
    var err error
    err = binFunc(add)
    fmt.Println(err)
    fmt.Println(i)
}

关于上面的代码,我有两个问题:

  • add函数转换为binFunc类型时,我不知道为什么会执行Error方法?
  • add函数转换的结果是如何赋值给一个错误接口变量的?

5
请提供更详细的示例,可以使用 https://play.golang.org/ 进行演示。我不太理解您所说的内容。什么是 add,什么是 binFunc - RoninDev
2个回答

13

error是一个接口:

type error interface {
    Error() string
}

这意味着任何具有方法:Error() string的类型都符合该接口并可以分配给error类型的变量。 binFunc具有这样的方法:
func (f binFunc) Error() string {
    return "binFunc error"
}

新手在使用Go语言时有时会感到困惑,因为他们没有意识到可以将方法附加到不止结构体上。在这种情况下,binFunc 的定义如下:
type binFunc func(int, int) int

所以这个机制的作用是允许你转换任何具有相同签名的函数(来自规范)。

函数类型表示具有相同参数和结果类型的所有函数的集合。

如果您创建一个函数add
func add(x, y int) int {
    return x + y
}

您可以将此转换为 binFunc

binFunc(add)

由于我们上面定义的binFunc方法中有Error方法,因此我们可以将这个新的binFunc赋值给一个error类型的变量。
var err error
var bf binFunc = binFunc(add)
err = bf
fmt.Println的行为是在错误上调用.Error()进行转换:
  1. 如果操作数实现了错误接口,将调用Error方法将对象转换为字符串,然后按照动词(如果有)所需的格式进行格式化。
因此回答您的问题:
  • Error方法被执行,因为fmt.Println查找类型为error的参数,调用.Error()并打印生成的字符串。
  • 您可以将binFunc分配给err,因为binFunc具有Error方法。 您不能直接将add分配给err,因为它没有Error方法。 但是,您可以将add转换为binFunc,因为它们具有相同的函数签名,通过这样做,您可以将其分配给err变量。

这篇帖子非常详细地解释了如何以及为什么将一个函数转换为特定的函数类型。谢谢! - undefined

0

Go语言规范依赖关系: 类型转换 -> 可赋值性 -> 类型标识

  1. 显式类型转换

binFuncfunc(int, int) int 具有相同的底层表示。

binFunc(add)

注意,类型转换可以在具有相同底层表示的2种类型之间发生。但是,它们的类型可能完全不同。

type MyInt int

func main() {
    var b MyInt = 3
    a := int(b)
    fmt.Println(a, b)
}

变量赋值
检查类型标识 根据类型标识规则,binFuncfunc(int, int) int相同。因此,您可以进行类型转换,如下所示:

命名类型始终与任何其他类型不同。否则,如果它们的基础类型文字结构等效,则两个类型是相同的;也就是说,它们具有相同的文字结构,并且相应的组件具有相同的类型。

func(int, int) int

type是字面量,而且它是无名的

type binFunc func(int, int) int

是一种命名类型

预声明类型、定义类型和类型参数被称为命名类型。如果别名声明中给出的类型是命名类型,则该别名表示一个命名类型。

命名类型与其他类型不同。但在这里,binFunc 与未命名类型进行比较:它们的基础类型文字结构上等效,都是 func(int, int) int

var bfunc binFunc = add

检查可分配性

命名类型的变量可以被赋予未命名类型的值,前提是它们的基础类型相同。

你可以在这里称之为隐式类型转换,但这并不准确。至少golang不称之为类型转换,因为基础类型/表示是相同的。

灵感来自这个答案

额外的话

类型断言只需要类型标识。因此,规则比类型可分配性更简单。


我还发现这个链接很有帮助:https://go101.org/article/type-system-overview.html - Izana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接