Short Variable Declarations
The := form declares and assigns in one step, works only inside functions, and needs at least one new name.
name := value // identical to: var name = valueInside a function, Go offers a shorter way to make a variable: :=. It declares the variable and gives it a value in one step.
The short form and the long form are the same thing
b := 2 and var b = 2 produce exactly the same variable. The short form is the long form with the word var and the type left out; the compiler infers the type from the value in both cases. Neither is faster or safer. Most Go code inside functions uses :=, so you need to read both and write both.
Two rules
- It only works inside a function. At the top level of a file there is no function, so a package-level variable must use
var. - At least one name on the left of
:=must be new. If every name already exists in that block, use plain=instead, which is assignment.
That second rule is what makes := comfortable for several values at once. name, n := "gadget", 4 is legal when n is new even if name is not: n is declared and name is simply assigned.
What trips people up
Using := where nothing is new gives "no new variables on left side of :=". The other trap is quieter. Inside a new block, := always makes a brand new variable, even when the same name exists outside. The outer one keeps its old value and nothing warns you.
Example
package main
import "fmt"
func main() {
// These two lines declare the same kind of variable.
// The first is the long form, the second is the short form.
var a = 2
b := 2
// Two names at once. Each type is inferred from its own value.
name, size := "widget", 3
// n is new on this line, so := is allowed.
// name already exists, so it is only assigned a new value.
name, n := "gadget", 4
fmt.Println(a, b)
fmt.Println(name, size, n)
}
// Output:
// 2 2
// gadget 3 4When to use it
- Naming the two results of a call, such as a parsed number and its error, on one line.
- Giving an intermediate calculation a name so the next line reads clearly.
- Overwriting a default with a value read at startup, using plain = instead of :=.
- Reading a value out of a map while also asking whether the key was present.
More examples
Taking two results from one call
This is the commonest use of := in real Go: one line that names both a result and the error that reports whether producing it worked. Later lessons cover what to do with that error. The signature is func Atoi(s string) (int, error).
package main
import (
"fmt"
"strconv"
)
func main() {
// strconv.Atoi turns text into a number. It hands back two values:
// the number, and an error value that reports failure.
// Nothing fails here, so err is nil, which means "no error".
n, err := strconv.Atoi("42")
fmt.Println(n, err)
// Text that is not a number fills the error and leaves the number at 0.
bad, badErr := strconv.Atoi("x42")
fmt.Println(bad, badErr != nil)
}
// Output:
// 42 <nil>
// 0 trueAt the top level of a file, var is the only option
Every file has some declarations outside any function, and := is not available there. Keep this in mind when you move a line out of a function and into package scope: the := has to become a var.
package config
// version := "1.0"
// The line above does not compile:
// syntax error: non-declaration statement outside function body
// Package-level variables need the long form.
var version = "1.0"
// Grouping works the same way at the top level.
var (
host = "localhost"
port = 8080
)When no name is new
Reach for this when you are overwriting values you already declared, for example replacing a default with something read from the environment. The compiler error names the exact problem, and the fix is always to drop the colon.
package main
import "fmt"
func main() {
host, port := "localhost", 8080
// host, port := "example.com", 443
// compile error: no new variables on left side of :=
// Plain = assigns to both existing variables.
host, port = "example.com", 443
fmt.Println(host, port)
}
// Output:
// example.com 443
Discussion