英文:
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函数转换的结果赋值给一个errerror 接口变量? 
英文:
// 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 
Errormethod executed, whenaddfunction was converted intobinFunctype? - Why the 
addfunction 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()来打印:
- 如果操作数实现了错误接口,则将调用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
Errormethod is executed becausefmt.Printlnlooks for arguments of typeerror, invokes.Error()and prints the resulting string. - 
You are allowed to assign
binFuncs toerrbecausebinFunchas anErrormethod. You cannot assignadddirectly toerrbecause it does not have anErrormethod. But you are allowed to convertaddto abinFuncbecause they have the same function signature, and by doing so you can then assign it to theerrvariable. 
答案2
得分: 0
go规范中的依赖关系:
类型转换或转换 -> 可赋值性 -> 类型标识
- 显式类型转换或转换
 
binFunc 和 func(int, int) int 具有相同的底层表示。
binFunc(add)
注意,类型转换可以发生在具有相同底层表示的两种类型之间。然而,它们的类型可以完全不同。
type MyInt int
func main() {
	var b MyInt = 3
	a := int(b)
	fmt.Println(a, b)
}
- 变量赋值
 
查看类型标识
根据类型标识规则,binFunc 与 func(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
- 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)
}
- 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论