带条件语句(if)问题的范围

I'm new to Go and I'm struggling with scope (as others).

The code below generates:

./excel.go:24: err declared and not used
./excel.go:25: sheet declared and not used

Why does this happen? I have declared both err and sheet in the parent scope, haven't I?

Excel.go:

package main

import (
    "os"
    "fmt"
    "github.com/tealeg/xlsx"
)

func main() {
    var file *xlsx.File
    var sheet *xlsx.Sheet
    var row *xlsx.Row
    var cell *xlsx.Cell
    var err error

    fileName := "MyXLSXFile.xlsx"

    if _, err := os.Stat(fileName); os.IsNotExist(err) {
        fmt.Printf("File does not exist so create one");
        file = xlsx.NewFile()
        sheet, err = file.AddSheet("Sheet1")
    } else {
        fmt.Printf("File exists so open");
        file, err := xlsx.OpenFile(fileName) // <-- line 24
        sheet := file.Sheets[0] // <-- line 25
    }

    row = sheet.AddRow()

    cell = row.AddCell()
    cell.Value = "I am a cell!"
    cell = row.AddCell()
    cell.Value = "I am another cell!"

    err = file.Save(fileName)

    if err != nil {
        fmt.Printf("help")
    }
}

Use = instead of :=:

    file, err = xlsx.OpenFile(fileName) // <-- line 24
    sheet = file.Sheets[0] // <-- line 25

Go allows re-declaring variables with the same name in nested blocks. := declares a new variable. In your case both err and sheet are declared inside else block but are not used there.

TL;DR: Use = for pure assignments. := declares a new variable.

sheet := file.Sheets[0] declares a new variable within the scope of the else block (see the chapter "Short variable declaration" from the language spec). This variable shadows the variable of the same name declared in the outer scope and will not exist in the outer scope (see the documentation):

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.

So the variable sheet in line 25 and the variable sheet in lines 12 and 28 are actually two different variables (with the first one declared in line 25 never being used after assignment).