:=运算符和Golang中的if语句

The following works as a function to open a file

func openFile(filename string) {
  var file *os.File
  var err error
  if file, err = os.Open(filename); err != nil {
    log.Printf("Failed to open the file: %s.", filename)
    return
  }
  defer file.Close()
  // blahblahblah
}

however, this does not work, when I try to use := to declare the variable file

func updateFrequencies(filename string, frequencyForWord map[string]int) {
  if file, err := os.Open(filename); err != nil {
     ....
  }
}

error: ./word_frequencies_2.go:30: undefined: file

But if I changed this slightly, this works

file, err := os.Open(filename)
if err != nil {
   log.Printf("Failed to open the file: %s.", filename)
   return
}

why can't I use := as part of the if statement?

Why can't I use := as part of the if statement?

You can, but then the variables are defined within the scope of the if block. So, file is not defined outside of your if block.

The same rule applies to definitions in for, switch, and similar blocks.

Mostafa already pointed that the file variable isn't defined out of the if block and you already saw how to fix that.

But your function has two more important problems.

The first one is that it doesn't return anything.

You could fix that by changing it to

func openFile(filename string) *os.File, error {
     ... implementation
     return file, nil
}

But that would let another one : when your function ends, it closes the file because of defer file.Close() so that the user of this function receives a closed file. The truth is that your function doesn't make really sense. You could fix it by letting it pass a callback that would use the file, or by letting the user close the file, but the right thing to do is to directly open the file where you need it.