Variables and Constants in Golang

Jyothi
6 min readFeb 15, 2025

--

Go is a statically typed language. Variables must have a type, either explicitly specified or inferred by the compiler.

1. Variables

A variable is a named storage location in memory that holds a value.

Declaring Variables

In Go, you can declare variables in several ways:

A) Using the var Keyword

package main
import "fmt"
func main() {
var name string = "Alice"
var age int = 25
var height float64 = 5.8
fmt.Println(name, age, height)
}
  • var name string = "Alice" → Explicitly declares a variable name of type string.
  • var age int = 25 → Declares age as an int.
  • var height float64 = 5.8 → Declares height as a float64.

B) Type Inference (Omitting Type)

Go allows type inference, meaning it automatically determines the type based on the assigned value.

package main
import (
"fmt"
"reflect"
)
func main() {
var city = "Hyd" // Go infers city as a string
var population = 80_00000_0 // there can be underscore in the middle of value
fmt.Println(city, population)
fmt.Println(reflect.TypeOf(city), reflect.TypeOf(population))
}
reflect.TypeOf() is used to know the type of the variable

C) Short Variable Declaration (:=)

Inside functions, you can use the shorthand declaration (:=), which is equivalent to var but more concise.

package main
import (
"fmt"
"reflect"
)
func main() {
name := "Alice"
age := 25
fmt.Println(name, age)
fmt.Println(reflect.TypeOf(name), reflect.TypeOf(age))
}

💡 Note: The := shorthand can only be used inside functions, get erros if used for global variables:

D) Multiple Variable Declaration

You can declare multiple variables at once:

package main
import (
"fmt"
"reflect"
)
func main() {
var x, y, z int = 1, 2, 3
a, b, c := "hello", 10, true
fmt.Println(x, y, z, a, b, c)
fmt.Println(reflect.TypeOf(a), reflect.TypeOf(c))
}

E) Zero Values (Default Initialization)

If you declare a variable without initializing it, Go assigns a default “zero value.”

package main
import (
"fmt"
"reflect"
)
func main() {
var num int // Defaults to 0
var str string // Defaults to "" (empty string)
var flag bool // Defaults to false
fmt.Println(num, str, flag)
fmt.Println(reflect.TypeOf(num), reflect.TypeOf(flag))
}

2. Constants

A constant is a variable whose value cannot be changed after declaration.

Declaring Constants

Use the const keyword:

package main
import (
"fmt"
"reflect"
)
func main() {
const pi float64 = 3.1415
const appName = "MyGoApp"
fmt.Println(pi, appName)
fmt.Println(reflect.TypeOf(pi), reflect.TypeOf(appName))
}
  • pi is a constant of type float64.
  • appName is a constant of type string.

Constants vs. Variables

constants and variables are both used to store data, but they have some key differences:

package main
import (
"fmt"
"reflect"
)
func main() {
var age = 25
name := "Alice"
age = 26 // Changing the value of age
const pi = 3.14
const greeting = "Hello, World!"
// pi = 3.14159 // This would cause an error:
//cannot assign to pi (neither addressable nor a map index expression)
fmt.Println(age, name, pi, greeting)
fmt.Println(reflect.TypeOf(age), reflect.TypeOf(pi))
}

Variables

  • Mutable: The value of a variable can change during the execution of a program.
  • Declaration: In Go, you declare a variable using the var keyword or the shorthand :=.

Constants

  • Immutable: Once a constant is assigned a value, it cannot be changed.
  • Declaration: In Go, you declare a constant using the const keyword.

Variables can be updated, while constants cannot. Use variables when you need to store data that might change. Use constants for fixed values that should not change throughout the program, such as mathematical constants or configuration values.

3. Constants with iota (Auto-Incrementing Values)

Go provides iota, which automatically generates incremental integer values.

package main
import (
"fmt"
"reflect"
)
func main() {
const (
A = iota // 0
B // 1
C // 2
)
fmt.Println(A, B, C) // expected output 0,1,2
fmt.Println(reflect.TypeOf(A), reflect.TypeOf(C))
}

💡 Tip: iota is useful for defining enumerations.

4. Constants with Expressions

Constants can be initialized using expressions.

package main
import (
"fmt"
"reflect"
)
func main() {
const x = 5 * 2 // Allowed
var y = x * 2 // Allowed
const z = y * 2 // ❌ ERROR (constants can't use non-constant values)
fmt.Println(x, y, z) // expected output 0,1,2
fmt.Println(reflect.TypeOf(x), reflect.TypeOf(z))
}

Example Program

package main
import "fmt"
func main() {
var name string = "Alice"
age := 30
const country = "USA"
fmt.Println("Name:", name)
fmt.Println("Age:", age)
fmt.Println("Country:", country)
// Uncommenting the line below will cause an error
// country = "Canada" // ❌ ERROR: Cannot change a constant
//cannot assign to country (neither addressable nor a map index expression)
}

Variables in Detail

A) Variable Scope: Global vs. Local

In Go, variables can be declared at the package level (global) or inside functions (local).

💡 Global variables are accessible across functions within the same package.

package main
import "fmt"
var globalVar = "I am global" // Accessible throughout the package
func main() {
localVar := "I am local"
fmt.Println(localVar) // ✅ Allowed
if true {
blockVar := "I exist only inside this block"
fmt.Println(blockVar) // ✅ Allowed
}
fmt.Println(globalVar) // ✅ Allowed
// fmt.Println(blockVar) // ❌ ERROR: blockVar is out of scope:
//undefined: blockVar
}

💡 Local variables exist only within their function or block.

B) Shadowing in Go

If a local variable has the same name as a global one, it shadows the global variable.

package main
import "fmt"
var message = "Global Message"
func main() {
message := "Local Message"
fmt.Println(message) // Output: Local Message (shadows global)
}

💡 Go will use the closest-scoped variable when resolving names.

C) Pointers and Variables

A pointer holds the memory address of a variable.

package main
import "fmt"
func main() {
x := 10
p := &x // `p` stores the memory address of `x`

fmt.Println("Value of x:", x) // 10
fmt.Println("Address of x:", p) // Some memory address
fmt.Println("Value at p:", *p) // 10 (dereferencing)
}

💡 Pointers are useful when passing large data structures efficiently.

2. Constants in Detail

A) Typed vs. Untyped Constants

Constants in Go can be typed or untyped.An untyped constant can be assigned to different types.

💡 Typed constants have a fixed type, while untyped constants adapt to their usage.

B) Constant Expressions

Constants support arithmetic operations.

💡 Expressions in constants must involve only constants.

D) iota with Bitwise Operations

iota simplifies sequential values. iota is useful for bit-masking.

package main
import (
"fmt"
"reflect"
)
func main() {
const typedInt int = 42 // Explicit type
const untypedInt = 42 // No type (flexible)
fmt.Println(typedInt, untypedInt)
fmt.Println(reflect.TypeOf(typedInt), reflect.TypeOf(untypedInt))
var x float64 = untypedInt // ✅ Allowed
fmt.Println(x, untypedInt)
fmt.Println(reflect.TypeOf(x), reflect.TypeOf(untypedInt))

const a = 10
const b = 20
const sum = a + b // Allowed
fmt.Println(a, b, sum)
fmt.Println(reflect.TypeOf(a), reflect.TypeOf(sum))
const (
Read = 1 << iota // 1 (0001)
Write // 2 (0010)
Execute // 4 (0100)
)
fmt.Println(Read, Write, Execute)
fmt.Println(reflect.TypeOf(Read), reflect.TypeOf(Execute))

p := &x // `p` stores the memory address of `x`
fmt.Println("Value of x:", x) // 10
fmt.Println("Address of x:", p) // Some memory address
fmt.Println("Value at p:", *p) // 10 (dereferencing)
}

💡 This is useful for defining permissions or flags.

3. Common Mistakes & Gotchas

A) Forgetting Variable Initialization

var x int
fmt.Println(x) // Output: 0 (default zero value)

💡 Always initialize variables when needed.

B) Misusing := Outside Functions

package main
var x := 10 // ❌ ERROR: := cannot be used at package level

💡 Use var instead of := outside functions.

C) Modifying Constants (Not Allowed)

💡 Constants are immutable in Go.

--

--

No responses yet