Go (Golang) Tutorial 0/45 lessons ~6 min read Lesson 4

    Variables and Data Types

    Go's type system is statically typed with type inference via the short declaration operator :=.

    Course progress0%
    Focus
    10 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Go's type system is statically typed with type inference via the short declaration operator :=. Understanding basic types, zero values, and when to use explicit types versus inference is foundational for every backend service you will build.

    Unlike C#, Go has no implicit numeric conversions — you must cast explicitly. Strings are immutable UTF-8 byte sequences. Understanding zero values (0, "", false, nil) prevents subtle bugs when variables are declared but not initialized.

    This lesson covers int, float64, bool, string, byte, rune, and the rules for variable shadowing in inner scopes — topics that appear frequently in Go coding interviews and code review discussions.

    The story

    A ride-sharing billing microservice (similar to Uber's ledger pipeline) stores each trip snapshot with a UUID, fare in cents as an integer, and a timestamp. Using int64 for money in the smallest currency unit avoids floating-point rounding bugs that have caused real payment discrepancies in production.

    When a rider receives a $12.50 credit, the service creates a new snapshot rather than mutating history — preserving the audit trail regulators expect from financial software deployed on GCP.

    Understanding the topic

    Key concepts

    • Basic types: bool, string, int, int8/16/32/64, uint, float32/64, complex64/128, byte (alias uint8), rune (alias int32).
    • var name type declares with zero value; name := value infers type (short declaration).
    • Zero values: 0 for numbers, false for bool, "" for string, nil for pointers/slices/maps/channels.
    • Type conversion: T(v) syntax — no implicit widening or narrowing.
    • const declares compile-time constants; iota creates enumerated constants.
    • Shadowing: inner := redeclares in inner scope — can hide outer variables.
    text
    classDiagram
    class ValueTypes {
    int
    float64
    bool
    struct
    }
    class ReferenceTypes {
    string
    slice
    map
    pointer
    }

    Step-by-step explanation

    1. Declare with var or := inside functions; := only works inside functions.
    2. Go infers type from literal: x := 42 is int, y := 3.14 is float64.
    3. Explicit conversion required: float64(i) * 1.5.
    4. Multiple declaration: a, b := 1, "hello".
    5. Blank identifier _ discards unwanted return values.
    6. Compiler rejects unused variables at package and function scope.

    Practical code example

    Demonstrating types, inference, conversion, and zero values in a payment calculation:

    go
    package main
    import "fmt"
    func main() {
    // Explicit type
    var balance float64 = 1000.50
    transactionCount := 3 // inferred int
    // Type conversion required
    feeRate := 0.025
    fee := balance * feeRate
    total := balance + fee
    // Multiple assignment
    accountID, currency := "ACC-001", "USD"
    // Zero value demo
    var pending bool // false
    fmt.Printf("Account %s (%s): balance=%.2f fee=%.2f total=%.2f txns=%d pending=%v\n",
    accountID, currency, balance, fee, total, transactionCount, pending)
    }

    Line-by-line code explanation

    • var tripID string declares a variable with the zero value (empty string).
    • tripID := uuid.New().String() uses short declaration with inference — the most common style.
    • const CurrencyUSD = "USD" defines a compile-time constant that cannot change.
    • fareCents int64 = 1250 stores $12.50 as 1250 cents — never use float64 for money.
    • time.Now().UTC() records when the snapshot was taken in UTC for API consistency.
    • fmt.Sprintf("%s-%d", tripID, fareCents) builds a log line without separate concatenation.
    • var count int zero-initializes to 0 — Go never leaves variables uninitialized.
    • count++ increments the accumulator in a loop processing trip batches.

    Key takeaway: Use float64 for general math; use shopspring/decimal or int64 cents for financial precision in production. Unused variables cause compile errors — Go enforces clean code.

    Real-world use

    Where you'll use this in production

    • Parsing and validating API request fields with explicit types.
    • Configuration values loaded from env vars into typed structs.
    • Metrics counters and gauges in observability agents.
    • Protocol buffer and JSON field mapping with strict types.

    Best practices

    • Prefer := for local variables when type is obvious from the right side.
    • Use int for loops and indices; int64 for IDs and timestamps (Unix epoch).
    • Store money as int64 cents or use decimal library — avoid float64 for currency.
    • Name variables descriptively; single-letter only in short loops (i, j, k).
    • Avoid shadowing — use different names or smaller scopes deliberately.
    • Use strconv for string↔number conversion with error checking.

    Common mistakes

    • Implicit conversion like Java — Go requires explicit T(v) casts.
    • Using float64 for money — rounding errors in financial systems.
    • Declaring variables with var and never assigning — zero value surprises.
    • Shadowing err in nested scopes — classic bug in error handling.
    • Using int when uint is needed for bit operations without understanding signedness.

    Advanced interview questions

    Q1BeginnerValue type vs reference type in Go?
    Structs, arrays, and numeric types are values (copied); slices, maps, channels, and pointers are reference-like (share underlying data).
    Q2BeginnerWhat is a zero value?
    Default value assigned when variable declared without initializer: 0, false, "", nil depending on type.
    Q3IntermediateDifference between var and :=?
    var works at package and function level; := is short declaration inside functions only, with type inference.
    Q4IntermediateWhy no implicit numeric conversion?
    Prevents silent precision loss and bugs — explicit T(v) makes conversions visible in code review.
    Q5AdvancedExplain variable shadowing and why it matters with err.
    Inner := creates new variable hiding outer; shadowing err prevents outer error from being checked — use err = or different name.

    Summary

    Go is statically typed with inference via := and explicit var declarations. Zero values apply automatically; no uninitialized variable undefined behavior. Type conversions are explicit — no implicit widening. Use appropriate types for domain: int64 for IDs, decimal for money. Next lesson: constants, operators, and iota enumerations.

    Ready to mark this lesson complete?Track your journey across the entire course.