正常情况
在编写具有命名返回值的函数时,您通常可以使用裸返回(是否应该单独讨论)。它们可能类似于以下内容:
func add(x, y int) (z int) {
z = x + y
return
}
return
这里的意思和return z
问题情况
但是下面的删节片段...
func loadModule(moduleName, fileRoot string) (module []byte) {
if strings.HasSuffix(moduleName, ".md") {
module, err := readConvertMDFile(fileRoot + "htdocs/md/" + moduleName)
if err != nil {
log.Println(err)
}
return module
} else {
module = []byte{}
return
}
}
(这段代码运行良好,是我目前解决问题的方法)
...编译器会提示 module is shadowed
如果不是 return module
只有 return
。这是因为 module
与 err
一起被声明(第二次),后者必须被声明,因为它在此范围内尚不存在。
可能的解决方案
照我做的做,明确命名返回变量。虽然这不是一个糟糕的解决方案,但我觉得好像应该有一种方法来安排代码,以便它可以正常运行并返回一个裸体。 Others have commented这种显式返回会导致“代码异味”。
在开头添加
var err error
,并使用多重赋值而不是声明。可能是更好的解决方案,但为了保持一致性并减少不必要的行,我更愿意尽可能使用隐式赋值。使用一个临时的
moduleT
变量然后赋值module = moduleT
...这让人感觉凌乱和多余。
虽然我可以获得我正在寻找的编译结果,但我希望有人可以建议一种清晰、惯用的编写方式。
最佳答案
我总是使用您建议的解决方案 2 - 添加一个额外的 var
语句。
func loadModule(moduleName, fileRoot string) (module []byte) {
var err error
if strings.HasSuffix(moduleName, ".md") {
module, err = readConvertMDFile(fileRoot + "htdocs/md/" + moduleName)
if err != nil {
log.Println(err)
}
return
} else {
// no need for this as module will be nil if it isn't written to
// a nil slice is perfectly legal and has len()=0
// and can be appended to etc
// module = []byte{}
return
}
}
选项 2 也是最有效的解决方案。请记住,go 返回堆栈上的所有值,因此命名返回值等同于堆栈分配的变量。
如果在选项 1 或选项 3 中您没有裸返回,那么那里无论如何都有一个隐式的 module = module
或 module = moduleT
语句。
不幸的是,变量阴影是每个 Go 程序员一段时间后都会遇到的问题。我非常希望编译器禁止函数内的所有阴影,因为它是真正错误的来源。
关于variables - 返回(可能被隐藏的)变量的惯用方式,这些变量已被定义为单独的多变量返回的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23255748/