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 type | Python equivalent | Description |
|---|---|---|
int | int | Integer (size depends on platform: 32 or 64 bit) |
int64 | int | Explicitly 64-bit integer |
float64 | float | 64-bit floating-point number |
string | str | UTF-8 text |
bool | bool | true 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
varwithout assigning a value: anint, astring, abool, and afloat64. - 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 (
299792458metres 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 := 7andb := 2.5. - Try to compute
a + bdirectly. What error do you get? - Fix it by converting
atofloat64.
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
varinstead of:=to declare a variable in Go? - Write two examples that demonstrate each use case.
💡 Show Answer
Use var when:
- Declaring a variable at package level (outside any function) —
:=is only valid inside functions. - You want to declare a variable without initialising it (relying on its zero value).
- 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)
}