convert function type in Golang

huangapple go评论87阅读模式
英文:

convert function type in Golang

问题

// 每个类型都有一个 Error() string 方法。
// error 内置接口类型是表示错误条件的常规接口,nil 值表示没有错误。
// 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 函数转换的结果赋值给一个 err error 接口变量?
英文:
// 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)
}

I have two questions about the code above:

  • I don't know why the Error method executed, when add function was converted into binFunc type?
  • Why the add function converted result was able to assign to an err error interface variable?

答案1

得分: 12

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变量。

英文:

error is an interface:

type error interface {
    Error() string
}

This means that any type which has a method: Error() string fulfills the interface and can be assigned to a variable of type error.

binFunc has such a method:

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

New developers in Go sometimes find this confusing because they don't realize it's possible to attach methods to more than just structs. In this case binFunc is defined liked this:

type binFunc func(int, int) int

So the way this works is you are allowed to convert any function which has the same signature: (from the spec)

> A function type denotes the set of all functions with the same parameter and result types.

So if you create a function add:

func add(x, y int) int {
    return x + y
}

You are allowed to convert this into a binFunc:

binFunc(add)

And because of the Error method on binFunc we defined above, we are then able to assign this new binFunc to a variable of type error:

var err error
var bf binFunc = binFunc(add)
err = bf

fmt.Println's behavior is to call .Error() on errors for you:

> 4. If an operand implements the error interface, the Error method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).

So to answer your questions:

  • The Error method is executed because fmt.Println looks for arguments of type error, invokes .Error() and prints the resulting string.

  • You are allowed to assign binFuncs to err because binFunc has an Error method. You cannot assign add directly to err because it does not have an Error method. But you are allowed to convert add to a binFunc because they have the same function signature, and by doing so you can then assign it to the err variable.

答案2

得分: 0

go规范中的依赖关系:
类型转换或转换 -> 可赋值性 -> 类型标识

  1. 显式类型转换或转换

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

binFunc(add)

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

type MyInt int

func main() {
	var b MyInt = 3
	a := int(b)
	fmt.Println(a, b)
}
  1. 变量赋值

查看类型标识

根据类型标识规则,binFuncfunc(int, int) int 是相同的。因此,您可以进行如下的类型转换

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

func(int, int) int

是类型文字,它是无名的

type binFunc func(int, int) int

是一个命名类型

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

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

var bfunc binFunc = add

查看可赋值性

命名类型的变量可以赋值为无名类型的值,前提是它们的底层类型是相同的。

在这里,可以称之为隐式类型转换,但这并不准确。至少在Go语言中,不称之为类型转换,因为底层类型/表示是相同的。

此答案的启发

额外的说明

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

英文:

go spec dependencies:
type casting or conversion -> assignability -> type identity

  1. explicit type casting or conversion

binFunc and func(int, int) int have same underlying representation.

binFunc(add)

note, type casting can happen between 2 types that have the same underlying representation. However, their type can be totally different.

type MyInt int

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

check type identity

based on type identity rule, binFunc is identical to func(int, int) int. So you can do type casting as below:

> A named type is always different from any other type. Otherwise, two types are identical if their underlying type literals are structurally equivalent; that is, they have the same literal structure and corresponding components have identical types.

func(int, int) int

is type literal, and it's unnamed.

type binFunc func(int, int) int

is a named type.

> Predeclared types, defined types, and type parameters are called named types. An alias denotes a named type if the type given in the alias declaration is a named type.

named type is different from others. but here, binFunc is compared with the un-named type: their underlying type literals are structurally equivalent, both func(int, int) int.

var bfunc binFunc = add

check assignability

variable of named type can be assigned with a value of unnamed type providing their underlying type is identical.

You may call this an implicit type conversion here, but it's not accurate. At least golang doesn't call this type conversion because the underlying type/representation is the same.

inspired by this answer

extra words

type assertion only requires type identity. Therefore, the rule is simpler than type assignability.

huangapple
  • 本文由 发表于 2015年9月4日 16:27:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/32393460.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定