Skip to main content

Variables & Types

Introduction​

Go is a statically typed language. Every variable has a type that is fixed at compile time and cannot change. This is the opposite of Python's dynamic typing, where a variable can hold any type of value and that type can change at runtime.

Static typing means the Go compiler catches many bugs before your program runs — if you try to add a string to an integer, the code simply won't compile. The trade-off is slightly more verbosity when declaring variables.

Go offers two ways to declare variables:

  • var name type = value — explicit declaration, useful when the type can't be inferred, or when declaring a variable without an initial value.
  • name := value — short declaration, the most common form. Go infers the type from the value.

Go also has zero values: every variable type has a default value if not explicitly initialised. int defaults to 0, string to "", bool to false, and pointers/slices/maps to nil.


Concepts​

Variable declaration​

var age int = 25 // explicit type
var name string = "Alice" // explicit type
score := 98.5 // type inferred as float64
isActive := true // type inferred as bool

Go's basic types​

Go typePython equivalentDescription
intintInteger (size depends on platform: 32 or 64 bit)
int64intExplicitly 64-bit integer
float64float64-bit floating-point number
stringstrUTF-8 text
boolbooltrue or false (lowercase in Go)
byte—Alias for uint8; often used for raw data
rune—Alias for int32; represents a Unicode code point

Zero values​

var i int // i == 0
var s string // s == ""
var b bool // b == false

Constants​

const Pi = 3.14159
const MaxSize = 100

Examples​

package main

import "fmt"

func main() {
// Short declaration — most common style
language := "Go"
year := 2009
version := 1.22
compiled := true

fmt.Printf("Language: %s\n", language)
fmt.Printf("Created: %d\n", year)
fmt.Printf("Version: %.2f\n", version)
fmt.Printf("Compiled: %v\n", compiled)

// Multiple assignment
x, y := 10, 20
fmt.Printf("x=%d, y=%d\n", x, y)

// Swap (no temp variable needed)
x, y = y, x
fmt.Printf("After swap: x=%d, y=%d\n", x, y)

// Zero values
var count int
var message string
fmt.Printf("Zero int: %d, Zero string: %q\n", count, message)
}

Challenges​

1. Declare variables for a person​

  • Declare variables for a person's first name, last name, age, and whether they are employed.
  • Print each variable and its type using %T.
💡 Show Answer
package main

import "fmt"

func main() {
firstName := "Alice"
lastName := "Smith"
age := 30
isEmployed := true

fmt.Printf("%v (%T)\n", firstName, firstName)
fmt.Printf("%v (%T)\n", lastName, lastName)
fmt.Printf("%v (%T)\n", age, age)
fmt.Printf("%v (%T)\n", isEmployed, isEmployed)
}

2. Static typing in action​

  • Declare x := 10.
  • Try to assign x = "hello" on the next line.
  • Run the code and read the compiler error.

Ask Copilot: Why won't Go let me assign a string to a variable that holds an integer?

💡 Show Answer

You will see: cannot use "hello" (untyped string constant) as int value in assignment. Once x is declared as int (via := 10), it can only ever hold integers. This is unlike Python, where x = 10; x = "hello" is perfectly valid.

Static typing helps catch bugs at compile time rather than at runtime, and makes code easier to reason about in large codebases.


3. Unused variable rule​

  • Declare a variable with := but never use it.
  • Try to run the code. What error do you get?

Ask Copilot: Why does Go make unused variables a compile error?

💡 Show Answer

You will see: declared and not used. Go enforces this to prevent dead code from accumulating. If you declare a variable, you must use it. In Python, unused variables are just a style warning from linters — they don't prevent execution.


4. Zero values​

  • Declare the following using var without assigning a value: an int, a string, a bool, and a float64.
  • Print each one and confirm the zero values.
💡 Show Answer
package main

import "fmt"

func main() {
var i int
var s string
var b bool
var f float64

fmt.Printf("int zero value: %d\n", i) // 0
fmt.Printf("string zero value: %q\n", s) // ""
fmt.Printf("bool zero value: %v\n", b) // false
fmt.Printf("float64 zero value: %v\n", f) // 0
}

5. Constants​

  • Declare a constant for the speed of light (299792458 metres per second) and another for its name ("c").
  • Print a sentence using both.

Ask Copilot: What is the difference between a constant and a variable in Go?

💡 Show Answer
package main

import "fmt"

const SpeedOfLight = 299792458
const SpeedOfLightSymbol = "c"

func main() {
fmt.Printf("The speed of light (%s) is %d m/s\n", SpeedOfLightSymbol, SpeedOfLight)
}

Constants are evaluated at compile time and cannot be changed. Variables are evaluated at runtime and can be reassigned. In Python, constants are a convention (usually UPPER_CASE) but the language does not enforce immutability.


6. Type conversion​

  • Declare a := 7 and b := 2.5.
  • Try to compute a + b directly. What error do you get?
  • Fix it by converting a to float64.

Ask Copilot: Why doesn't Go automatically convert between numeric types?

💡 Show Answer
package main

import "fmt"

func main() {
a := 7
b := 2.5
// result := a + b // compile error: mismatched types int and float64
result := float64(a) + b
fmt.Println(result) // 9.5
}

Go never performs implicit type conversion between numeric types, even when the conversion is "safe". You must be explicit. Python 3 does this automatically (7 + 2.5 gives 9.5), but Go prioritises explicitness to avoid subtle bugs in numeric code.


7. Multiple return values (preview)​

  • Ask Copilot: Show me a Go function that returns both a result and an error, and how to use the blank identifier _ to ignore one of the return values.
  • Read and run the example Copilot generates.
💡 Show Answer
package main

import (
"fmt"
"strconv"
)

func main() {
// strconv.Atoi converts a string to an int, returning (int, error)
number, err := strconv.Atoi("42")
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Number:", number)
}

// Ignore the error with _ (blank identifier)
number2, _ := strconv.Atoi("100")
fmt.Println("Number2:", number2)
}

The blank identifier _ discards a value you don't need. Python uses _ by convention for the same purpose, but Go requires all declared variables to be used — _ is the only way to intentionally discard one.


8. var vs :=​

  • Ask Copilot: When should I use var instead of := to declare a variable in Go?
  • Write two examples that demonstrate each use case.
💡 Show Answer

Use var when:

  1. Declaring a variable at package level (outside any function) — := is only valid inside functions.
  2. You want to declare a variable without initialising it (relying on its zero value).
  3. You want to be explicit about the type.
// Package-level — must use var
var GlobalCounter int

func main() {
// Inside a function — := is idiomatic
name := "Alice"

// var is fine here too, especially when type matters
var score float64 // zero value 0.0, not 0
score = 98.6
fmt.Println(name, score)
}