ToolPopToolPop
Go · Lesson 2 of 22

Variables, types, and the zero-value trick

6 min readUpdated 25 Jun 2026

If you are coming from JavaScript, the first thing that will jump out about Go is that variables have types and the compiler will yell at you. The second thing is that nothing is ever undefined. Both of these are gifts. This lesson covers how Go declares variables, the basic types, and the zero-value rule that quietly removes a whole category of 3 AM bugs.

Two ways to declare, one you will use 95% of the time

Go has var and :=. They do almost the same thing.

go
var count int = 10
var name = "Razorpay"   // type inferred as string
city := "Bengaluru"     // short form, only inside functions

The := short form is what you will reach for inside functions. It declares and assigns in one line. Use var at the package level, or when you want the zero value without assigning.

go
var price float64   // price is 0.0, ready to use
var active bool     // active is false
var users []string  // users is nil, but you can still append to it

Senior rule: prefer := inside functions for readability, but use var x T when you specifically want the zero value as your starting point.

The basic types you will actually use

Go has many numeric types. In real code, you reach for a handful.

  • int: the default integer. 64-bit on modern machines. Use this for counts, indices, IDs that fit.
  • int64: when you specifically need 64 bits, like UPI transaction amounts in paise or Unix nanoseconds.
  • float64: the default float. Use for prices, ratios, anything fractional. Never use float32 unless you have a reason.
  • string: immutable bytes, usually UTF-8. len(s) returns bytes, not characters.
  • bool: true or false. No truthy nonsense.
  • byte and rune: aliases for uint8 and int32. byte for raw bytes, rune for a Unicode code point (one Devanagari character).
go
amount := 49900          // int, paise
upiRef := "ZHJ8K2M"      // string
verified := true         // bool
gst := 18.0              // float64

You will spend most of your career in these five. The other numeric types exist for when the wire protocol says so.

The zero-value trick

Every type in Go has a zero value. If you declare a variable without assigning to it, you get that zero value. Not undefined, not a crash, a real usable value.

  • int, float640
  • string""
  • boolfalse
  • pointers, slices, maps, channels, functions, interfaces → nil
  • struct → every field set to its own zero value

This sounds boring until you realise what it removes. There is no "uninitialised garbage" in Go. There is no if (x !== undefined && x !== null) dance at the top of every function. The variable exists. It has a value. You can use it.

go
var orders []string
orders = append(orders, "order-001")  // works, even though orders was nil

Senior rule: Go's zero values are not "default values you might forget to set". They are part of the type contract. Designing your structs so the zero value is useful is idiomatic Go.

Constants and iota

Constants are compile-time values. Declare with const. The iota keyword inside a const block auto-increments, perfect for enums.

go
const (
    StatusPending  = iota // 0
    StatusPaid            // 1
    StatusRefunded        // 2
    StatusFailed          // 3
)

No magic numbers in your handlers. The compiler now knows these are a related set, and you can attach a method to a typed iota for stringification later.

When the compiler saves you

Try to assign a string to an int variable and the compiler refuses, with a clear "cannot use string as int" message. You will hit this on day one and roll your eyes. By month three, you will realise the compiler caught a bug that would have been a 2 AM Slack ping in Node. The same goes for shadowing, unused variables, and unused imports. Go treats every one of these as a build break, not a warning, which keeps real codebases honest.

Diagram
rendering diagram...

Quick reference

Zero value
The default value every Go variable gets when declared without assignment. Safe to use, never undefined.
:=
Short variable declaration. Declares and assigns. Only legal inside functions.
var
Long-form declaration. Works at package level. Use when you want the zero value explicitly.
iota
Auto-incrementing identifier inside a const block. Used for enum-like sets.
rune
Alias for int32. Represents a single Unicode code point.
Type inference
The compiler figuring out the type from the right-hand side. Lets you skip type annotations on locals.

Next lesson, functions and the err pattern. That is where Go starts looking really different.

Chai0/2 done

Watching quietly. Tap me if you want a tip.

Go Playground

Go cannot run natively in a browser. Run copies your code and opens go.dev/play ; paste and click Run there.

Try this (0 of 2 done)

  1. 1

    What is the output? (Hint: zero values for int, string, bool.)

    hint

    int -> 0, string -> "" (empty), bool -> false

    show answer
    package main
    
    import "fmt"
    
    func main() {
    	var n int
    	var s string
    	var b bool
    	fmt.Println(n, s, b)
    }
  2. 2

    Predict: what does `const Pi = 3.14; fmt.Println(Pi * 2)` print?

    show answer
    package main
    
    import "fmt"
    
    func main() {
    	const Pi = 3.14
    	fmt.Println(Pi * 2)
    }