为什么Go编译器不将未声明的变量视为错误?

huangapple go评论95阅读模式
英文:

Why doesn't the Go compiler treat non-declared variable as error?

问题

我一直在编写一个辅助学习Go语言的测试程序。在这个过程中,我遇到了几个情况,我认为编译器应该检测到错误。我遇到了另一种类似的情况,所以我想问一下为什么这种情况不被视为错误。

示例情况:

在上面的示例中,无论变量"oError"是否声明,编译器都不会指示错误。如果变量未声明,则在行中包含以下内容时也可以正常工作(如预期所示):

如果我声明变量"oError",那么":="就不起作用(如预期所示)。

"rwfile"是我编写的一个包,相关函数的开头如下:

如果我在文件写入过程中创建一个错误,并且在不声明变量"oError"的情况下使用"=",程序将正常工作并检测到非nil的"oError"变量。

那么,为什么在上述情况下,当"oError"未声明为变量时,使用"="不被视为错误呢?

Go版本是go1.1.2 Windows/386。

英文:

I've been writing a test program to assist in learning Go. While doing so, I've encountered a few instances where I thought the compiler should have detected an error. I've encountered another similar situation, so I thought I should ask why this situation is not treated as an error.

Example situation :

if oError = rwfile.WriteLines(asParams, sParamsFilename); oError != nil {
    fmt.Printf("Error on write to file Params. Error = %s\n", oError)
} else {
    println("Params file write OK")
}

In the example above, whether or not the variable "oError" is declared, the compiler does not indicate an error. It also works if the line contains the following when the variable is not declared (as expected):

if oError := rwfile.WriteLines(asParams, sParamsFilename); oError != nil {

If I declare the variable "oError", then ":=" does not work (as expected).

"rwfile" is a package that I have written, and the function in question starts as follows:

func WriteLines(asBuff []string, sFilename string) error { // write text file

If I create an error with the write of the file, and use "=" without declaring the variable "oError", the program works correctly and detects the non-nil "oError" variable.

So, why is use of "=" in the above not treated as an error when oError is not declared a variable?

The Go version is go1.1.2 Windows/386.

答案1

得分: 8

这意味着在包的其他地方有一个名为oError的变量。(请注意,这个变量不一定在同一个文件中,它可以在具有相同包声明的不同文件中。)因此,当你使用oError = ...时,你正在给该包变量赋值,而当你使用oError := ...时,你正在声明一个隐藏包变量的局部变量。(根据规范,"在一个块中声明的标识符可以在内部块中重新声明。在内部声明的标识符在作用域内时,它表示内部声明所声明的实体。" 链接

如果你尝试使用一个不同的标识符,一个唯一的标识符,你应该会看到编译器确实会报错。

英文:

This means that you have an variable named oError elsewhere in the package. (Note that this variable need not be in the same file; it could be in a different file with the same package clause.) So, when you use oError = ..., you're assigning a value to that package variable, and when you use oError := ..., you're declaring a local variable that hides the package variable. (Per the specification, "An identifier declared in a block may be redeclared in an inner block. While the identifier of the inner declaration is in scope, it denotes the entity declared by the inner declaration." [link])

If you try a different identifier, a unique one, you should see that the compiler indeed complains.

答案2

得分: 2

这与实际问题无关,但是go fmt确实可以帮助追踪大型程序中的错误内容。
此外,遵循样式指南也非常有帮助:使用简洁的代码风格(不要使用匈牙利命名法!我花了很长时间才习惯使用短名称)和短文件:一个2Kloc的文件可能太大了。浏览标准库源代码,看看优秀的Go代码是什么样子,这是非常值得的。

英文:

<p>It's unrelated to the actual question, but go fmt can really help with tracking errant stuff in a big program.</p>
<p>Also, following the style guidelines really helps: use terse code styles (no hungarian variable names! took me ages to get used to short names) and short files: a 2Kloc file is probably too big. It's massively worth taking a wander through the standard library source code to see what good Go code looks like</p>

huangapple
  • 本文由 发表于 2013年10月13日 12:31:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/19341877.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定