我对此感到非常困惑,首先编写代码:
package main
import (
"fmt"
)
type FE struct {
myMsg string
ChainedError *error
}
func (fe FE) Error() (e string) {
if fe.ChainedError == nil {
return fe.myMsg
}
ce := *fe.ChainedError
return fe.myMsg + ce.Error()
}
func test() (error){
err := fmt.Errorf("test error")
newError := FE{
ChainedError: &err,
}
return newError
}
func testStackOverflow() (err error) {
err = fmt.Errorf("test error")
newError := FE{
ChainedError: &err,
}
return newError
}
func main() {
e := test()
fmt.Println(e)
e2 := testStackOverflow()
fmt.Println(e2)
}
根据我对函数签名的表述,我会得到堆栈溢出错误或预期的行为。
我不想谈论为什么或是否有这样的连锁错误是一个好主意。
让我生气的问题是:
命名和未命名的返回值之间的“低级”区别是什么
我认为命名返回值纯粹是语法糖。对我而言,编译器不会“看到”
之间的任何区别func a() (string) {
var s string
s = "hello world"
return s
}
func b() (s string) {
s = "hello world"
return
}
以我的直觉,编译器(或构建链中的编译器)会将命名的返回值“转换”为声明。因此,“在机器代码中” a()
和b()
将完全相同。
我认为上面的错误示例表明它是错误的。
我目前的感觉是:一个命名的返回值声明并为返回值“在调用者的范围内”(此处为main()
)分配内存,而被调用函数的return
则写“ afterwards”该内存的返回值。
我对程序流程了解的伪代码没有命名返回值
main{
allocate memory for return type of function to be called
function call {
internal allocation of return variable
return of return variable (memory address or value)
}
return value of function called gets written to allocated memory
}
我的感觉伪代码带有命名返回值
main{
allocate memory for return type of function to be called
function call, give allocated memory as "argument" to function {
execution of return(returnValue) writes returnValue to "in main allocated memory"
}
说实话:这令我感到困惑。如果函数的命名返回值表示被调用函数写入调用方作用域分配的内存,而不是调用方随后将返回值写入内存分配...那不是谁“拥有” /的问题什么时候可以“访问”哪个范围?
如果命名的返回值不仅仅是语法糖,则go tour:Go's return values may be named. If so, they are treated as variables defined at the top of the function.
的第一行会产生误导作用