Shawn
Shawn

Reputation: 71

Golang: no new variables on left side of :=, while a similar one didn't occur this error

I have written some code to prints the content found at a URL following the guide of a book named The Go Programming Language. The compiler complained about the following code that no new variables on left side of :=.

package main

import (
    "fmt"
    "net/http"
    "os"
    "io"
)

func main() {
    for _, url := range os.Args[1:] {
        resp, err := http.Get(url)
        if err != nil {
            fmt.Fprintf(os.Stderr, "fetch: %v\n", err)
            os.Exit(1)
        }
        _, err := io.Copy(os.Stdout, resp.Body)
        resp.Body.Close()
        if err != nil {
            fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err)
            os.Exit(1)
        }
    }
}

And I have known that this was caused by re-declaration of certain variables. While the following one passed the compilation.

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
)

func main() {
    for _, url := range os.Args[1:] {
        resp, err := http.Get(url)
        if err != nil {
            fmt.Fprintf(os.Stderr, "fetch: %v\n", err)
            os.Exit(1)
        }
        b, err := ioutil.ReadAll(resp.Body)
        resp.Body.Close()
        if err != nil {
            fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err)
            os.Exit(1)
        }
        fmt.Printf("%s", b)
    }
}

Didn't it re-declare the variable err? Then how could it pass the compilation?

Upvotes: 6

Views: 9563

Answers (2)

Maciej Długoszek
Maciej Długoszek

Reputation: 437

It did not

You can use the := as long as there is at least one new variable at the left side and the other variables have already been declared in the same block with the same type. Already declared variables will just have their values changed. It's basically for convenience.

It is all described here : https://golang.org/ref/spec#Short_variable_declarations

Upvotes: 4

Corey Ogburn
Corey Ogburn

Reputation: 24717

If there are any new variables in the assignment (e.g. b) then := will create it. If all variables are not new then you get the error you're getting. _ is not a new variable.

Since you have all existing variables you can just use = for your io line:

_, err = io.Copy(os.Stdout, resp.Body)

When you used b instead of _ then := declared b but treated err like a standard assignment (i.e. just as if a = was used)

Upvotes: 13

Related Questions