Go Variables and Data Types — var := Zero Values and Constants Explained
In this tutorial, you will learn about Go Variables and Data Types. We cover key concepts, practical examples, and best practices to help you master this topic.
Go variables use var with explicit types or := for type inference with static typing, zero values for automatic initialization, and constants declared with const keyword.
What You'll Learn
- Declaring variables with var and :=
- Basic data types: int, float64, string, bool
- Zero values and their importance
- Constants and iota enumerations
Why It Matters
Go's type system prevents entire classes of bugs at compile time. Docker uses strong typing for configuration structs. Kubernetes relies on typed API objects. DodaZIP uses Go types for file metadata and compression parameters. Understanding Go's typing is essential for writing correct code.
Real-World Use
A web API handler decodes JSON into typed structs, validates fields with specific types, and returns typed responses. A CLI tool uses typed flags and configuration structs. Every Go program depends on variables and types.
flowchart LR
A["Variables"] --> B["Declaration"]
B --> C["Types"]
C --> D["Zero Values"]
D --> E["Constants"]
A:::current --> B
style A fill:#2563eb,stroke:#2563eb,color:#fff
style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b
Variable Declaration
Using var
package main
import "fmt"
func main() {
var name string = "Alice"
var age int = 25
var height float64 = 1.68
var active bool = true
fmt.Println(name, age, height, active)
}
Type Inference with var
var name = "Alice" // string
var age = 25 // int
var height = 1.68 // float64
var active = true // bool
Short Declaration :=
name := "Alice" // string
age := 25 // int
height := 1.68 // float64
active := true // bool
:= declares and assigns in one step. It can only be used inside functions.
Multiple Variables
var x, y int = 10, 20
a, b := "hello", 42
var (
name = "Alice"
age = 25
active = true
)
Basic Data Types
Integers
var a int = 42 // Platform-dependent (32 or 64 bit)
var b int8 = 127 // -128 to 127
var c int16 = 32767 // -32768 to 32767
var d int32 = 2147483647 // -2^31 to 2^31-1
var e int64 = 9223372036854775807
// Unsigned
var u uint = 42
var u8 uint8 = 255 // 0 to 255
// Type conversion
var i int = 42
var f float64 = float64(i)
var s string = strconv.Itoa(i)
Floats
var f32 float32 = 3.14 // ~6 decimal digits precision
var f64 float64 = 3.14159 // ~15 decimal digits precision
var c1 complex64 = 1 + 2i
var c2 complex128 = 3 + 4i
Strings
var s1 string = "Hello"
var s2 = "World"
s3 := "Go Programming"
// String concatenation
full := s1 + ", " + s2
// String length
fmt.Println(len(full))
// String indexing (byte access)
fmt.Println(full[0]) // 72 (ASCII 'H')
// Multi-line strings
multi := `Line 1
Line 2
Line 3`
Booleans
var active bool = true
var done bool = false
fmt.Println(active && done) // false
fmt.Println(active || done) // true
fmt.Println(!active) // false
Zero Values
Go automatically assigns zero values to uninitialized variables:
var i int // 0
var f float64 // 0
var s string // ""
var b bool // false
var p *int // nil
var arr [3]int // [0, 0, 0]
var sl []int // nil
var m map[int]string // nil
This eliminates the "undefined variable" bugs common in other languages.
Constants
const Pi = 3.14159
const AppName = "MyApp"
const MaxRetries = 3
// Typed constant
const Port int = 8080
// Multiple constants
const (
StatusOK = 200
StatusNotFound = 404
StatusError = 500
)
Iota Enumeration
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
const (
_ = iota // 0 (ignored)
KB = 1 << (10 * iota) // 1024
MB // 1048576
GB // 1073741824
)
Type Conversion
Go requires explicit type conversion:
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
// String conversion
var score int = 95
var s string = strconv.Itoa(score) // "95"
var n, _ = strconv.Atoi("42") // 42
Scope
package main
import "fmt"
var global = "accessible everywhere" // Package level
func main() {
var local = "only in main" // Function level
fmt.Println(global)
fmt.Println(local)
if true {
var block = "only in if" // Block level
fmt.Println(block)
}
// fmt.Println(block) // Error: undefined
}
Common Mistakes
1. Using := Outside Functions
// Wrong
package main
name := "Alice" // := not allowed outside function
// Right
var name = "Alice"
2. Unused Variables
func main() {
x := 5
y := 10 // y declared but not used — compilation error!
_ = x // Use 'x' to make it "used"
}
3. Confusing = and :=
x := 5 // Declaration + assignment
x = 10 // Assignment only
// x := 20 // Error: no new variables on left side
4. Integer Overflow
var x int8 = 127
x = x + 1 // Overflows to -128 (no compile error, but unexpected)
5. String Index Returns Byte, Not Rune
s := "Hello"
fmt.Println(s[0]) // 72 (byte value), not 'H'
6. Not Converting Types
var i int = 42
var f float64 = i // Error: cannot use i (type int) as float64
var f = float64(i) // Correct
Practice Questions
1. What is the zero value of a string?
An empty string "". All Go types have zero values assigned automatically without explicit initialization.
2. What's the difference between var and :=?
var can be used at package and function level, explicitly announces type. := is function-level only, infers type from the value. Use := inside functions for conciseness.
3. How do you declare a constant in Go?
Use the const keyword: const Pi = 3.14159. Constants can be typed or untyped. Untypes constants have flexible types until used in context.
4. What is iota?
Iota is a special constant generator that increments for each constant in a const block. It starts at 0 and increases by 1 for each subsequent constant.
Challenge: Write a Go program that uses var, :=, constants with iota, and demonstrates type conversion between int, float64, and string.
Solution
package main
import (
"fmt"
"strconv"
)
const (
Small = iota
Medium
Large
)
func main() {
var product string = "Widget"
price := 19.99
quantity := 5
total := price * float64(quantity)
report := product + ": " + strconv.FormatFloat(total, 'f', 2, 64)
fmt.Println("Product:", product)
fmt.Println("Price:", price)
fmt.Println("Quantity:", quantity)
fmt.Println("Total:", total)
fmt.Println("Report:", report)
fmt.Printf("Sizes: Small=%d, Medium=%d, Large=%d\n", Small, Medium, Large)
}
FAQ
{{< faq question="Why does Go have multiple integer types?" >}}
Different sizes for different needs. int8/int16/int32/int64 give precise control over memory usage and range. Use int for general use and specific sizes for binary protocols or memory-constrained systems.
{{< /faq >}}
{{< faq question="What happens if I try to assign a float to an int without conversion?" >}} Compilation error. Go requires explicit type conversion for all type changes, even between numeric types. This prevents accidental precision loss. {{< /faq >}}
{{< faq question="Can I change a variable's type after declaration?" >}} No. Go is statically typed. Once declared, a variable's type is fixed for its lifetime. You can convert values to new types and assign to new variables. {{< /faq >}}
{{< faq question="Why are untyped constants useful?" >}}
Untyped constants (declared without explicit type) can be used with any compatible type. const Pi = 3.14 can be used as float32, float64, or complex64 without conversion.
{{< /faq >}}
{{< faq question="What's the difference between int and int64?" >}}
int is platform-dependent (32-bit on 32-bit systems, 64-bit on 64-bit systems). int64 is always 64-bit. Use int for general use unless you need specific sizing.
{{< /faq >}}
Try It Yourself
package main
import "fmt"
func main() {
// Declaration styles
var a int = 10
var b = 20
c := 30
// Multiple
x, y := "hello", 42
// Zero values
var z int
var s string
var ok bool
fmt.Println("Declared:", a, b, c)
fmt.Println("Multiple:", x, y)
fmt.Println("Zero values:", z, s, ok)
fmt.Printf("Types: a=%T, x=%T, y=%T\n", a, x, y)
}
Expected output:
Declared: 10 20 30
Multiple: hello 42
Zero values: 0 false
Types: a=int, x=string, y=int
What's Next
Now that you understand variables, learn about control flow with if/else, for, switch, and defer.
| Topic | Description | Link |
|---|---|---|
| Go Control Flow | if/else, for, switch, defer | {{< ref "05-control-flow" >}} |
| Go Functions | func, returns, multiple returns | {{< ref "06-functions" >}} |
| Rust Variables | Compare Rust variables | Rust |