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

时间:2011-09-07 05:50:04

标签: variables go

新编程/甚至更新。使用小型程序时遇到问题 - 不会使用未定义的变量错误进行编译。代码:

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")
}

和错误:

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

但是,在代码运行之前,不会定义这些变量。另外,“查找”功能尚未写入,它只返回传递的内容。我知道查找和enterdisk函数自己工作,但我试图测试switch语句。

我试过在main中声明变量,但是我得到了这个错误:

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。我已阅读http://tip.goneat.org/doc/go_faq.html#unused_variables_and_imports,我同意如果这只是语义,我仍然想解决它。我只是不知道怎么做!

2 个答案:

答案 0 :(得分:4)

blocks中了解declarations and scopeGo

  

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

     

阻止嵌套并影响范围。

     

声明的标识符的范围是源文本的范围   其中标识符表示指定的常量,类型,变量,   功能或包装。

     

在a中声明的常量或变量标识符的范围   函数从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")) 

artist albumyearswitchcasedefault个变量的short variable declarations范围case子句在每个子句(最里面的包含块)内开始和结束。 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"))
  

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

因此,在{case}子句中使用short variable declarations不再声明(和分配)artistalbumyear变量,因为这会隐藏变量在外部区块中的声明,它们仅被分配。

答案 1 :(得分:2)

如果有条件地分配变量,则必须在条件之前声明它们。所以而不是:

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)
}

(即使你设置了一个默认值,编译器也不喜欢它们没有被声明为第一个。或者它可能不喜欢它们被声明两次,每个条件一个,我不确定)< / p>

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