go编译错误:未定义的变量

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

go compile errors: undefined variables

问题

package main

import (
"fmt"
"io"
"os"
)

const file = "readfile.txt"
var s string

func lookup(string) (string, string, string) {
artist := s
album := s
year := s

return artist, album, year

}

func enterdisk() (string, string, string) {
var artist string
var album string
var year string

println("enter artist:")
fmt.Scanf("%s", &artist)

println("enter album:")
fmt.Scanf("%s", &album)

println("enter year:")
fmt.Scanf("%s", &year)

return artist, album, year

}

func main() {

println("enter UPC or [manual] to enter information manually:")
fmt.Scanf("%s", &s)

s := s
switch s {
	case "manual\n": artist, album, year := enterdisk()
	default: artist, album, year := lookup(s)
}

f,_ := os.OpenFile(file, os.O_APPEND|os.O_RDWR, 0666)
io.WriteString(f, (artist + ", \"" + album + "\" - " + year + "\n"))

f.Close()
println("wrote data to file")

}

英文:

new to programming / even newer to go. having trouble with a small go program - will not compile with undefined variable errors. the code:

package main

import (
  "fmt"
  "io"
  "os"
)

const file = "readfile.txt" 
var s string

func lookup(string) (string, string, string) {
	artist := s
	album := s
	year := s
	
	return artist, album, year
}

func enterdisk() (string, string, string) {
  var artist string
	var album string
	var year string
	
	println("enter artist:")
  fmt.Scanf("%s", &artist)
	
	println("enter album:")
  fmt.Scanf("%s", &album)

	println("enter year:")
  fmt.Scanf("%s", &year)
	
	return artist, album, year
}

func main() {
	
  println("enter UPC or [manual] to enter information manually:")
  fmt.Scanf("%s", &s)
	
	s := s
  switch s { 
		case "manual\n": artist, album, year := enterdisk()
		default: artist, album, year := lookup(s)
  }
	
	f,_ := os.OpenFile(file, os.O_APPEND|os.O_RDWR, 0666) 
  io.WriteString(f, (artist + ", \"" + album + "\" - " + year + "\n")) 

	f.Close()
	println("wrote data to file")
}

and the errors:

catalog.go:49: undefined: artist
catalog.go:49: undefined: album
catalog.go:49: undefined: year

however, those variables will not be defined until the code runs. additionally, the "lookup" function is not yet written, which it just returns what it is passed. i know the lookup and enterdisk functions work on their own, but i am trying to test the switch statement.

i have tried declaring the variables in main, however i get this error:

catalog.go:49: artist declared and not used
catalog.go:49: album declared and not used
catalog.go:49: year declared and not used

p.s. i have read http://tip.goneat.org/doc/go_faq.html#unused_variables_and_imports , and i agree that if this is only semantics, i still want to fix it. i just don't know how!

答案1

得分: 5

阅读关于Go中的blocksdeclarations and scope的内容。

在switch或select语句中的每个子句都充当隐式块。

块可以嵌套并影响作用域。

声明的标识符的作用域是源代码中标识符指定的常量、类型、变量、函数或包的范围。

在函数内部声明的常量或变量标识符的作用域从ConstSpec或VarSpec(对于短变量声明为ShortVarDecl)的结束开始,并在最内层包含块的结束处结束。

switch s { 
    case "manual\n": artist, album, year := enterdisk()
    default: artist, album, year := lookup(s)
}
. . .
io.WriteString(f, (artist + ", \"" + album + "\" - " + year + "\n")) 

switchcasedefault子句中,artistalbumyear变量的短变量声明的作用域在每个子句内部(最内层包含块)开始和结束。artistalbumyear变量不再存在,并且对WriteString()语句不可见。

改为:

var artist, album, year string
switch s {
case "manual\n":
	artist, album, year = enterdisk()
default:
	artist, album, year = lookup(s)
}
. . .
io.WriteString(f, (artist + ", \"" + album + "\" - " + year + "\n"))

与常规变量声明不同,短变量声明可以重新声明变量,前提是它们最初在同一块中以相同的类型声明,并且至少有一个非空白变量是新的。因此,重新声明只能出现在多变量的短声明中。

因此,在switch case子句中不再使用短变量声明来声明(和赋值)artistalbumyear变量,因为这会隐藏外部块中的变量声明,它们只是被赋值。

英文:

Read about blocks and declarations and scope in Go.

> Each clause in a switch or select statement acts as an implicit block.
>
> Blocks nest and influence scoping.
>
> The scope of a declared identifier is the extent of source text in
> which the identifier denotes the specified constant, type, variable,
> function, or package.
>
> The scope of a constant or variable identifier declared inside a
> function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
> for short variable declarations) and ends at the end of the innermost
> containing block.

switch s { 
    case "manual\n": artist, album, year := enterdisk()
    default: artist, album, year := lookup(s)
}
. . .
io.WriteString(f, (artist + ", \"" + album + "\" - " + year + "\n")) 

The scope of the short variable declarations of the artist, album, and year variables in the switch case and default case clauses begins and ends within each clause (the innermost containing block). The artist, album, and year variables no longer exist and are not visible to the WriteString() statement.

Instead, write:

var artist, album, year string
switch s {
case "manual\n":
	artist, album, year = enterdisk()
default:
	artist, album, year = lookup(s)
}
. . .
io.WriteString(f, (artist + ", \"" + album + "\" - " + year + "\n"))

> Unlike regular variable declarations, a short variable declaration may
> redeclare variables provided they were originally declared in the same
> block with the same type, and at least one of the non-blank variables
> is new. As a consequence, redeclaration can only appear in a
> multi-variable short declaration.

Therefore, the artist, album, and year variables are no longer declared (and assigned) using short variable declarations inside the switch case clauses because that would hide the variable declarations in the outer block, they are merely assigned.

答案2

得分: 3

当您有变量被有条件地赋值时,您必须在条件之前声明它们。所以,不要这样写:

switch s { 
    case "manual\n": artist, album, year := enterdisk()
    default: artist, album, year := lookup(s)
}

...试试这样写:

var artist, album, year string

switch s { 
    case "manual\n": artist, album, year = enterdisk()
    default: artist, album, year = lookup(s)
}

(即使您设置了一个默认值,编译器也不喜欢它们没有先声明。或者也许它不喜欢它们在每个条件中都声明了两次,我不确定)

您看,现在我们首先声明了变量,在switch条件内设置了它们的值。一般规则是:如果您要在if/switch/for之外使用变量,请先声明它们,以便在将要使用的范围内访问它们。

英文:

When you have variables being assigned conditionally, you must declare them before the conditions. So instead of:

switch s { 
    case "manual\n": artist, album, year := enterdisk()
    default: artist, album, year := lookup(s)
}

...try this:

var artist, album, year string

switch s { 
    case "manual\n": artist, album, year = enterdisk()
    default: artist, album, year = lookup(s)
}

(even though you have set a default, the compiler doesn't like that they are not declared first. Or maybe it doesn't like that they are declared twice, one in each condition, I'm not sure)

You see, now first we declare the variables, and inside the switch condition their values are set. The general rule is: if you are going to use the variables outside of the if/switch/for, declare them first to make them accessible in the scope they will be used.

huangapple
  • 本文由 发表于 2011年9月7日 13:50:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/7329389.html
匿名

发表评论

匿名网友

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

确定