Chapter 6: Go Variables
Go Variables — one of the very first things you actually use when writing real code.
Variables in Go are storage locations that hold values (numbers, text, booleans, etc.). Go is statically typed (type decided at compile time) and strongly typed (very few automatic conversions), but it has excellent type inference so you don’t write types everywhere.
I’ll explain like your friendly teacher sitting next to you in VS Code: rules, why they exist, two main declaration styles, zero values, scope, common patterns, pitfalls, and lots of examples you can copy-paste and run right now.
1. Two Ways to Declare Variables (The Heart of Go Variables)
Go gives you exactly two main styles — and the community strongly prefers the short one inside functions.
| Style | Keyword / Symbol | Where allowed | Type must be written? | Most idiomatic? | Example |
|---|---|---|---|---|---|
| Full var declaration | var | Anywhere (package or function level) | Usually yes (can infer with initializer) | No — verbose | var age int = 25 |
| Short declaration | := | Only inside functions | No — always inferred | Yes — 80–90% of cases | age := 25 |
Why two ways?
- var is required at package level (outside any function).
- := is syntactic sugar for cleaner, less repetitive code inside functions (introduced to make Go feel modern and productive).
2. Full var Declaration — The Classic Way
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package main import "fmt" var globalCount int = 100 // package-level (global), can be used anywhere in package func main() { var name string = "Webliance" // explicit type + value var age int // type only → gets zero value (explained below) var height, weight float64 = 175.5, 70.0 // multiple vars, same type var ( isStudent bool = true city string = "Hyderabad" temperature int // zero value ) fmt.Printf("Name: %s, Age: %d (zero? %t), City: %s\n", name, age, age == 0, city) } |
Output (age is 0 because no value given):
|
0 1 2 3 4 5 6 |
Name: Webliance, Age: 0 (zero? true), City: Hyderabad |
When to use var:
- Package-level variables
- When you want to declare without initializer (planning to set later)
- When type clarity helps readability (rare)
- In some var blocks for grouping related vars
3. Short Declaration := — The Go Way (Most Common)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
func main() { name := "Webliance" // type string inferred age := 25 // int height, isTall := 175.5, true // multiple, different types ok temperature := 32.0 // float64 (not float32!) fmt.Printf("%s is %d years old and %.1f cm tall. Tall? %t\n", name, age, height, isTall) } |
Important rules for :=:
- Can only be used inside functions (not at package level)
- At least one new variable must be declared on the left (see redeclaration below)
- Types are always inferred from the right-hand side expression
- Very common with function calls: f, err := os.Open(“file.txt”)
4. Redeclaration with := (Powerful & Safe Feature)
You can re-use := in the same scope if at least one variable is new.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
func main() { x := 10 fmt.Println("x =", x) // 10 x, y := 20, 30 // x is re-assigned, y is new fmt.Println("x =", x, "y =", y) // 20 30 // This is INVALID — no new variable // x := 40 // compile error: no new variables on left side of := // But this is fine (shadowing — new x in inner scope) if true { x := 100 // new x, shadows outer x fmt.Println("inner x =", x) // 100 } fmt.Println("outer x still =", x) // 20 } |
Shadowing tip: Be careful — inner x := … creates a new variable, outer one unchanged.
5. Zero Values — What Happens When No Initializer?
Go never has uninitialized variables — every variable gets a zero value automatically.
| Type family | Zero value | Example if var x T |
|---|---|---|
| Numeric (int, float64, etc.) | 0 / 0.0 | var n int // n == 0 |
| Boolean | false | |
| String | “” (empty string) | |
| Pointers (*T) | nil | var p *int // p == nil |
| Slices, maps, channels | nil | var s []int // s == nil |
| Interfaces | nil | |
| Structs | All fields zero | |
| Arrays | All elements zero |
This is super helpful — no “undefined behavior” like C/C++.
6. Type Inference — How Smart Is It?
Go infers from literals, constants, function returns:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
i := 42 // int f := 3.14 // float64 (not float32!) c := 'A' // rune (int32 alias) s := "hello" // string b := true // bool ptr := &i // *int slice := []int{1,2,3} // []int m := make(map[string]int) // map[string]int |
Note: Un-typed constants get “ideal” type, but when assigned to var, concrete type chosen (usually int / float64).
7. Package-Level vs Function-Level Variables
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package main import "fmt" var global int = 100 // visible to whole package, initialized once func main() { local := 50 // only in main() fmt.Println(global, local) // You can change global global = 200 } |
Globals → use sparingly (thread-safety issues with goroutines later).
8. Quick Mini-Project Example (Putting It Together)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package main import ( "fmt" "time" ) func main() { // Short style everywhere name := "Webliance" age := 25 heightCm := 175.5 isLearningGo := true birthYear := time.Now().Year() - age var favoriteColor string // zero value "" favoriteColor = "Blue" // assign later fmt.Printf("%s (%d years old, born ~%d) from Hyderabad\n", name, age, birthYear) fmt.Printf("Height: %.1f cm | Learning Go: %t | Fav color: %s\n", heightCm, isLearningGo, favoriteColor) } |
Output example:
|
0 1 2 3 4 5 6 7 |
Webliance (25 years old, born ~2001) from Hyderabad Height: 175.5 cm | Learning Go: true | Fav color: Blue |
Summary Table — When to Use What
| Situation | Recommended Style | Why |
|---|---|---|
| Inside function, with value | x := value | Clean, short, idiomatic |
| Inside function, no initial value | var x Type | Clear you plan to assign later |
| Package level (global/constant-like) | var x Type = value | Required — no := allowed |
| Multiple related vars | var ( … ) block | Groups them nicely |
| From function return (err common) | f, err := os.Open(…) | Classic error handling pattern |
Common Beginner Mistakes
- Using := at package level → compile error
- Forgetting to use a variable → compile error (no unused vars!)
- var x = 3.14 → float64, but if you want float32: var x float32 = 3.14
- Shadowing by accident → x := … inside if/for creates new var
Ready to practice? Create variables.go, try declaring 5–6 vars with different styles, mix var and :=, print zero values, and redeclare something.
Questions now?
- Want deep dive on pointers with variables?
- Slices/maps as variables?
- How variables work with goroutines (race conditions)?
- Or next topic: constants? functions? structs?
You’re progressing super fast — keep typing code! 💻🇮🇳 Let’s go! 🚀
