Перейти ошибки компиляции: неопределенные переменные - PullRequest
3 голосов
/ 07 сентября 2011

новичок в программировании / еще новее. возникли проблемы с небольшой программой 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

однако, эти переменные не будут определены, пока код не будет запущен. кроме того, функция «lookup» еще не написана, и она просто возвращает то, что было передано. я знаю, что функции поиска и ввода работают самостоятельно, но я пытаюсь проверить оператор 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 ]

4 голосов
/ 07 сентября 2011

Читать о блоках и декларациях и области действия in Go .

Каждое предложение в операторе 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")) 

Область действия кратких объявлений переменных переменных artist, album и year в предложениях case switch case и default начинается и заканчивается в каждом пункт (самый внутренний содержащий блок). Переменные artist, album и year больше не существуют и не видны оператору 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"))

В отличие от обычных объявлений переменных, краткое объявление переменной может Переопределить переменные, если они были первоначально объявлены в том же блок с таким же типом и хотя бы одной из непустых переменных новый. Как следствие, объявление может появиться только в краткая краткая декларация.

Следовательно, переменные artist, album и year больше не объявляются (и не присваиваются) с помощью кратких объявлений переменных внутри выражений case switch, поскольку это скрыло бы объявления переменных в внешний блок, они просто назначены.

2 голосов
/ 07 сентября 2011

Если переменные назначаются условно, вы должны объявить их перед условиями. Так что вместо:

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

(даже если вы установили значение по умолчанию, компилятору не нравится, что они не объявляются первыми. Или, может быть, не нравится, что они объявляются дважды, по одному в каждом условии, я не уверен)

Видите ли, теперь сначала мы объявляем переменные, а внутри условия переключателя устанавливаются их значения. Общее правило: если вы собираетесь использовать переменные вне if / switch / for, сначала объявите их, чтобы сделать их доступными в той области, в которой они будут использоваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...