Home

Published

- 5 min read

Variables, Constants, and Types in Go (The Right Way)

img of Variables, Constants, and Types in Go (The Right Way)

Understanding variables, constants, and types in Go isn’t just about syntax—it’s about embracing the philosophy behind Go’s minimalism and clarity. Go doesn’t overload you with features, but what it does give you, it expects you to use intentionally.

Variable Declarations in Go

Go offers flexible ways to declare variables, either using the concise short declaration := inside functions with automatic type inference, or the explicit var keyword for package-level variables or when you want to specify types or zero values. Understanding when and how to use each helps you write clear and idiomatic Go code.

Short Variable Declaration (:=)

It is used within functions, := lets the compiler infer the type from the right-hand side.

   fruit := "Apple"  // string
count := 3       // int
ratio := 3.14    // float64
  • This works inside functions only and you cannot use := at the package level
  • The compiler infers the type based on the assigned value using static analysis at compile time
  • It’s very concise and idiomatic for local variables

Explicit Declaration with var

   var city string = "Kathmandu"
var country = "Nepal"
var isActive bool
  • Use var for package-level variables, or when you want to declare without immediate initialization
  • You can omit the explicit type if you initialize immediately (var country = "Nepal"), and Go will infer the type automatically
  • When declared without initialization (var isActive bool), variables get their zero value (here: false)
DeclarationType inference?Where valid?
fruit := “Apple”YesInside functions only
var city string = “Kathmandu”No (explicit)Package-level and function scope
var country = “Nepal”YesPackage-level and function scope
var isActive boolNo (zero value)Package-level and function scope

Zero Values: Go’s Safety Net

If you declare a variable without initializing it, Go assigns a zero value depending on its type:

TypeZero Value
int0
boolfalse
string""
pointers, slices, maps, interfacesnil

Constants in Go

Use const for values that never change. Constants must be initialized with compile-time constant expressions

   const Pi = 3.14

You can group constants:

   const (
    StatusOK = 200
    StatusError = 500
)

Use iota for enumerations:

   const (
    Red = iota
    Green
    Blue
)

Here,

  • iota is a predeclared identifier in Go.
  • It’s used within constant declarations to generate successive untyped integer constants, starting from 0.
  • It resets to 0 each time a new const block starts, and increments by 1 with each new line.

So in this example:

Constant NameValue
Red0
Green1
Blue2

Types in Go

Go is statically typed, meaning every variable has a fixed type determined at compile time.

Basic types

TypeSizeZero ValueDescriptionUse Case Example
bool1 bytefalseBoolean true/false valueFlags, conditional logic
stringvaries (UTF-8)"" (empty)Sequence of bytes interpreted as UTF-8 textText data, identifiers
int32 or 64 bits (arch)0Signed integer, size depends on system architectureDefault integer type
int88 bits0Signed 8-bit integer (-128 to 127)Memory-efficient counters
int1616 bits0Signed 16-bit integerCompact integer storage
int3232 bits0Signed 32-bit integerOften used with rune
int6464 bits0Signed 64-bit integerLarge numbers, timestamps
uint32 or 64 bits0Unsigned integer, depends on system architectureNon-negative numbers
uint88 bits0Unsigned 8-bit integer (0 to 255)Alias: byte; used for raw data
uint1616 bits0Unsigned 16-bit integerCompact positive integers
uint3232 bits0Unsigned 32-bit integerBitflags, positive IDs
uint6464 bits0Unsigned 64-bit integerHigh-precision counters
byte8 bits (alias)0Alias for uint8, represents a single raw byteBinary I/O, buffers
rune32 bits (alias)0Alias for int32, represents a Unicode code pointCharacters, text parsing
float3232 bits0.032-bit IEEE-754 floating pointMemory-efficient decimals
float6464 bits0.064-bit IEEE-754 floating pointDefault for floating-point math
complex6464 bits(0+0i)Complex number with float32 real/imag partsSignal processing, scientific math
complex128128 bits(0+0i)Complex number with float64 real/imag partsHigh-precision complex calculations
Notes:
  • int, uint: Use when size isn’t critical; the size depends on whether you’re on a 32-bit or 64-bit architecture.
  • byte, rune: Not separate types—just aliases with semantic meaning.
  • complex64 and complex128: Rarely used in typical application development, but supported natively for mathematical applications.

Custom Types

You can define your own types based on existing ones:

   type Age int

var myAge Age = 29

This adds semantic meaning and improves type safety.

Type Conversion

Go does not allow implicit type conversion. You must convert explicitly:

   var x int = 42
var y float64 = float64(x)  // explicit conversion

Variable Scope and Lifetime

  • Variables declared inside functions have local scope
  • Variables declared at package level have global package scope and exist throughout the program lifetime
  • Use var at package level; := is invalid there
   package main

var globalVar = "I am global"

func main() {
    localVar := "I am local"
    fmt.Println(globalVar, localVar)
}

Common Mistakes

Shadowing with :=

   x := 10
if true {
    x := 20  // shadows outer x; this is a *new* variable
    fmt.Println(x)  // prints 20
}
fmt.Println(x)      // prints 10

To modify an existing variable, use = instead of :=.

Using var unnecessarily inside functions

   var fruit = "Apple" // verbose inside functions
fruit := "Apple"    // preferred inside functions

Forgetting to use const for fixed values

   var Pi = 3.14    // mutable, avoid this for constants
const Pi = 3.14  // immutable, preferred

Final Thoughts

Mastering how Go handles variables, constants, and basic types is more than just syntax—it’s about embracing Go’s design philosophy of simplicity, clarity, and correctness.

Here’s what to keep in mind:

  • Use := for concise, idiomatic variable declarations inside functions.
  • Use var when declaring at the package level or when you need zero-initialized values.
  • Use const for values that never change—it’s safer, clearer, and helps the compiler optimize.
  • Understand Go’s type system, including how zero values work and when to use explicit types.
  • Use iota for clean, maintainable enumerations or bit flags.

By applying these practices early, you’ll write Go code that’s not just functional but idiomatic, predictable, and robust.