Chapter 7: Declare Variables
Declare Variables — so let’s zoom in purely on the declaration part itself.
Declaring a variable in Go means telling the compiler:
- “Hey, I want to create a named storage spot in memory”
- “This spot will hold values of a certain type”
- “Optionally give it an initial value right away”
Go is very strict about declarations — no undeclared variables allowed, no unused variables allowed (compiler error!), and types are checked at compile time.
There are mainly 3 practical ways to declare variables in real Go code (2026 style). I’ll explain each one like we’re typing together in VS Code, with pros/cons, when to use which, and full runnable examples.
1. The Classic var Declaration (Explicit & Verbose)
This is the most “traditional” way — similar to C, Java, etc.
Syntax patterns:
|
0 1 2 3 4 5 6 7 8 |
var name type // no initial value → zero value var name type = expression // with initial value var name1, name2 type = expr1, expr2 // multiple |
Real examples:
|
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 28 29 30 31 32 33 |
package main import "fmt" func main() { // 1. Type only → gets zero value automatically var count int // count == 0 var message string // message == "" var active bool // active == false // 2. With initial value (type can sometimes be omitted if obvious) var score int = 95 var username string = "Webliance" var pi float64 = 3.1415926535 // 3. Multiple declarations in one line var x, y int = 10, 20 // 4. Grouped var block (very clean for related variables) var ( city string = "Hyderabad" temperature int = 32 isSummer bool = true ) fmt.Printf("Score: %d | User: %s | Pi: %.4f\n", score, username, pi) fmt.Printf("City: %s | Temp: %d°C | Summer? %t\n", city, temperature, isSummer) } |
When to prefer this style (2026 community advice):
- At package level (outside any function) — := is not allowed there!
- When declaring without an initial value (you plan to assign later)
- In big var blocks to group configuration/options
- When you want the type to be very visible for readability (rare nowadays)
2. Short Variable Declaration with := (The Go Favorite — Idiomatic!)
This is the most common way you’ll see in modern Go code.
Syntax:
|
0 1 2 3 4 5 6 7 |
name := expression // type inferred from expression name1, name2 := expr1, expr2 |
Important rules:
- Only allowed inside functions (not at package level)
- Must introduce at least one new variable (or compile error)
- Type is always inferred — no need to write it
Real examples:
|
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 |
func main() { // Simple cases name := "Webliance" // inferred as string age := 25 // inferred as int height := 175.5 // inferred as float64 // Multiple at once lat, long := 17.3850, 78.4867 // both float64 // Very common pattern: function returns multiple values // (e.g. file open, http request, etc.) // file, err := os.Open("config.json") // Redeclaration is allowed if at least ONE is new age := 25 // first declaration age, city := 26, "Hyderabad" // age reassigned, city is new fmt.Println(name, age, height, lat, long, city) } |
When to prefer :=:
- 80–90% of declarations inside functions
- When you have an obvious initial value (especially from function calls)
- For loop variables, error handling, quick locals
- Makes code shorter and cleaner
Gotcha — you cannot do this at package level:
|
0 1 2 3 4 5 6 7 8 9 10 |
// INVALID outside functions global := 100 // compile error: := outside function // Correct: var global = 100 // or var global int = 100 |
3. Rare / Special Cases (You’ll See These Occasionally)
- Type inference with var (allowed since early Go, but less common now):
|
0 1 2 3 4 5 6 7 |
var temperature = 32.0 // inferred float64 var status = true // inferred bool |
- Declaring and ignoring (use _ for unused return values):
|
0 1 2 3 4 5 6 |
_, err := fmt.Println("Hello") // ignore the byte count |
- Shadowing (re-declaring same name in inner scope — careful!):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
func main() { x := 10 if true { x := 100 // new x in this block — shadows outer fmt.Println(x) // prints 100 } fmt.Println(x) // prints 10 — outer unchanged } |
Quick Comparison Table (Choose Wisely!)
| Style | Syntax Example | Allowed Location | Type Written? | Best For | Idiomatic Level (2026) |
|---|---|---|---|---|---|
| Full var | var x int = 42 | Anywhere | Yes | Package level, no init value | Medium |
| var with inference | var x = 42 | Anywhere | No | Grouping, package level | Low–Medium |
| Short := | x := 42 | Only inside functions | No | Everyday function code, errors, loops | Very High |
| Grouped var (…) | var ( a=1; b=”hi” ) | Anywhere | Optional | Related config/options | High for grouping |
Your Tiny Practice Task Right Now
Create a file declare.go and try all styles:
|
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 |
package main import "fmt" var globalScore int = 100 // package level var func main() { player := "Webliance" // short level := 5 // short var lives int // var no init → 0 lives = 3 // assign later var ( city string = "Hyderabad" temp int = 32 ) fmt.Printf("%s at level %d | Global: %d | Lives: %d | %s %d°C\n", player, level, globalScore, lives, city, temp) } |
Run go run declare.go
Any confusion left?
- Package vs local declarations?
- Why no unused variables?
- How := works with multiple returns?
- Pointer declaration? (var p *int vs p := &x)
- Or ready for next topic: constants, functions, pointers?
Keep asking — you’re building a really solid foundation step by step! 💪🇮🇳 Let’s keep going! 🚀
