4. Variables: naming your values

📖 Reading · 9 min
💡 Most code boxes below are live — edit one and hit Run. Boxes without a Run button are reference-only (they can't run in your browser).

A variable is a name that holds a value. Go gives you two ways to make one, and a strong opinion about which to use where.

The full form: var

package main

import "fmt"

func main() {
    var name string = "Dennis"
    var age int = 39

    fmt.Println(name, "is", age)
}

var name string = "Dennis" reads left to right: declare a variable called name, of type string, with the value "Dennis". Notice the type comes after the name — the opposite of C or Java. Go reads this way on purpose; it's more consistent once you get used to it.

Let Go figure out the type

Almost always, Go can see the type from the value, so you can drop it:

package main

import "fmt"

func main() {
    var name = "Dennis" // type inferred as string
    var age = 39        // type inferred as int

    fmt.Printf("%s (%T), %d (%T)\n", name, name, age, age)
}

The short form: :=

Inside a function, there's an even shorter way that Go programmers use by default — the short variable declaration, :=. It declares and assigns in one step, always inferring the type:

package main

import "fmt"

func main() {
    name := "Dennis"
    age := 39
    active := true

    fmt.Println(name, age, active)
}

:= only works inside a function. At the package level (outside any function) you must use var. Rule of thumb: reach for := almost every time; use var when you want to declare something without an initial value, or at package scope.

Zero values: nothing is ever undefined

Declare a variable without giving it a value and Go doesn't leave it as garbage — it gets that type's zero value. There is no "uninitialized" in Go.

package main

import "fmt"

func main() {
    var count int
    var price float64
    var label string
    var ready bool

    fmt.Printf("int=%d float=%v string=%q bool=%t\n", count, price, label, ready)
}
  • numbers → 0
  • strings → "" (empty string)
  • booleans → false

This is why Go code rarely worries about "is this set yet?" — it always is.

Assigning vs declaring

:= declares a new variable. Once it exists, use plain = to change it — no colon. Using := again on the same name in the same scope is an error.

package main

import "fmt"

func main() {
    score := 10 // declare
    score = 25  // reassign — note: = not :=
    score = score + 5
    fmt.Println(score)
}

Unused variables are errors

Declare a variable and never use it, and the real Go compiler refuses to build. Like unused imports, this isn't nagging — it kills a whole class of bugs (typos, dead code, the variable you meant to use but didn't). This program fails to compile with go build:

package main

import "fmt"

func main() {
    x := 42 // declared and not used  → compile error: x declared and not used
    fmt.Println("hello")
}

(That box is reference-only: the in-browser interpreter is lenient about this particular check, so it would run here — but on your own machine go build rejects it. The fix is always the same: use the variable, or delete it.)

Multiple at once

You can declare or assign several variables on one line — handy, and essential later when functions return more than one value:

package main

import "fmt"

func main() {
    x, y := 3, 4
    x, y = y, x // swap, no temp variable needed
    fmt.Println(x, y)
}

Your turn

Declare a variable celsius set to 100, compute fahrenheit as celsius*9/5 + 32, and print exactly:

100C = 212F
package main

import "fmt"

func main() {
    celsius := 100
    // compute fahrenheit and print the line
}
package main

import "fmt"

func main() {
    celsius := 100
    fahrenheit := celsius*9/5 + 32
    fmt.Printf("%dC = %dF\n", celsius, fahrenheit)
}

Next: a proper look at Go's basic types.