SPOOL导出指定格式的Oracle数据文件
为了方便数据的处理,或者本身有特殊的数据格式要求,我们可以使用SPOOL命令导出Oracle数据库数据数据文件,并指定格式,高效且强大...
问题复现
调试 Go 程序报错 xx is shadowed during return,该错误一般是在编译的时候产生。
找到错误的位置,优先分析是不是存在相同的变量名所致。
复现代码如下:
func main() {
no, err := makeErr()
fmt.Println(no, err)
}
func makeErr() (no int, err error) {
if err != nil {
no, err := doSomeWork1()
fmt.Println(no, err)
return
}
return
}
func doSomeWork1() (int, error) {
return 1, nil
}
报错提示如下:
# command-line-arguments
.main.go:16:3: no is shadowed during return
.main.go:16:3: err is shadowed during return
错误描述
关于错误的完整解释如下:
It's a new scope, so a naked return returns the outer err. So it's almost certainly not what you meant, hence the error.
这是一个全新的作用域,如果直接返回时会将外部变量一起返回。因此,返回的内容可能不是你预期希望的内容。
问题分析
我们对上面复现的代码进行分析,报错位置代码为:
no, err := doSomeWork1()
fmt.Println(no, err)
// 这里的return报错了
return
因为在 if err != nil 作为分支条件时,在 if 内的内容是一个全新的作用域。
因此,编写代码是 no, err := doSomeWork1() 不会报错,反之如果没有产生新的作用域时,这句代码编译会提示报错 No new variables on left side of :=。
func makeErr() (no int, err error) {
// No new variables on left side of :=
no, err := doSomeWork1()
fmt.Println(no, err)
return
}
因为方法的返回定义中定了变量名,func makeErr() (no int, err error) ,因此方法中直接写 return 也不会报错。
修改方案
避免重名
对于新作用域的变量,不建议与外部变量同名,可以考虑定义特别的名字。
func makeErr() (no int, err error) {
if err != nil {
// 内部作用域,定义其他名字
no1, err1 := doSomeWork1()
fmt.Println(no1, err1)
// 可以考虑赋值给外部变量(根据具体业务区考虑)
no = no1
err = err1
// 进行外部赋值的时候,一遍多用于多分支场景,内部可以不return
return
}
return
}
单独返回
如果不想定义太多的变量名,可以为内部分支或作用域直接返回具体的信息,已达到预期的返回内容。
func makeErr() (no int, err error) {
if err != nil {
no, err := doSomeWork1()
fmt.Println(no, err)
// 内部作用域直接绑定返回
return no, err
}
return
}
不提供返回名
这个方案在编写方法前可以考虑采用,具体使用还是依照业务场景具体分析。
如果方法返回定义没有定义变量名时,所有的 return 必须具体到所有的返回变量。
func makeErr() (int, error) {
no, err := doSomeWork1()
fmt.Println(no, err)
// 内部作用域直接绑定返回
return no, err
// 错误:Not enough arguments to return
return
}
