Go语言的language specification 中概括了几个内置的、predeclared identifiers (预声明的标识符),这些标识符不应该在Go程序中再次用作名称。
依赖于上下文,重新将这些标识符用做名称,将会遮盖原始标识符在当前的词法作用域(以及任何嵌套作用域)或者混淆代码,影响正常的代码逻辑。
最好的情况是,编译器将会报错。最坏的情况是,这样的代码可能会引起潜在的、难以捕捉的bug。
Bad
var error string
// `error` 覆盖了内建的error词法作用域
// or
func handleErrorMessage(error string) {
// `error` 返回值名称 error,覆盖了内建的error词法作用域
}
type Foo struct {
// 虽然这些字段技术上讲可行, 但是
// `error` or `string` 字符串语义上模棱两可
error error
string string
}
func (f Foo) Error() error {
// `error` and `f.error` 表面上是相似的
return f.error
}
func (f Foo) String() string {
// `string` and `f.string` 表面上相似的
return f.string
}
Good
var errorMessage string
// `error` refers to the builtin
// or
func handleErrorMessage(msg string) {
// `error` refers to the builtin
}
type Foo struct {
// `error` and `string` 现在就很明确了
err error
str string
}
func (f Foo) Error() error {
return f.err
}
func (f Foo) String() string {
return f.str
}
请注意,当使用预先声明的标识符时,编译器是不会生成错误的,但是go vet等工具应该能够正确地指出这些和其他隐藏的情况。