What Matters
- Every Go variable always has a value: if you do not initialize it explicitly, Go gives it the zero value for its type.
varand:=both create variables, but:=is limited to function bodies whilevarworks at package scope and can declare a variable without an explicit initializer.- Go’s basic types are intentionally explicit: integers, floating-point values, booleans, strings, bytes, and runes have different meanings, and Go generally does not perform silent numeric conversions for you.
Go tries to make basic program state predictable. Variables have known types, every declared variable starts with a defined value, and the language avoids many implicit conversions that can hide mistakes.
This lesson follows OSGo.001: What Is Go?, which introduced packages, the toolchain, go run, go build, and a first program. OSGo.002 moves inside the program itself: how to declare data, how Go chooses types, and what happens when you do not provide an initial value.
The official Go language specification defines variables as storage locations containing values of a particular type. That type determines which operations are valid and what zero value is used when initialization is omitted.
Declaring Variables With var
The most explicit form places var, the variable name, and the type together:
var miners int
No initializer appears here, but miners is still usable. Because its type is int, Go initializes it to that type’s zero value, which is 0.
You can declare and initialize in one statement:
var miners int = 128
var model string = "S21"
var online bool = true
When the initializer makes the type obvious, Go can infer the variable type:
var miners = 128
var model = "S21"
var online = true
Short Variable Declarations With :=
Inside a function, Go provides the short declaration operator:
miners := 128
model := "S21"
efficiency := 17.5
:= both declares the variable and initializes it. The compiler infers the type from the expression on the right side.
The short form cannot be used at package scope. Package-level variables use var. Inside a function, := is common when the type is obvious from the initializer.
var versus := highlights an important beginner distinction: explicit zero-value declarations communicate different intent from short initialized declarations.Every Variable Has a Zero Value
Go does not leave ordinary variables with an undefined garbage value. If you declare a variable without an initializer, the language initializes it to the zero value for its type.
- numeric types →
0 bool→falsestring→""- pointers, slices, maps, channels, functions, and interfaces →
nil
package main
import "fmt"
func main() {
var count int
var temperature float64
var online bool
var model string
fmt.Println(count) // 0
fmt.Println(temperature) // 0
fmt.Println(online) // false
fmt.Println(model) // empty string
}
This design is one reason Go APIs often try to make a useful zero value possible. Later lessons on structs, slices, maps, mutexes, and interfaces will show where zero values are especially useful—and where nil needs more careful handling.

Go Has Several Integer Types
Go provides signed and unsigned integer types at defined widths:
int8,int16,int32,int64uint8,uint16,uint32,uint64intanduint, whose size is implementation dependent but is either 32 or 64 bitsuintptr, an unsigned integer type large enough to store the uninterpreted bits of a pointer value
var temperature int32 = -5
var fanRPM uint16 = 5400
var total uint64 = 10_000_000_000
Use plain int for ordinary integer arithmetic unless the problem, protocol, file format, API, or memory layout requires a particular width.
byte and rune Are Integer Aliases
Two Go names deserve special attention:
byteis an alias foruint8.runeis an alias forint32and is conventionally used for Unicode code points.
var packet byte = 0xff
var symbol rune = 'λ'
var gopher rune = '🐹'
The type aliases do not create brand-new underlying integer representations. Their names communicate intent: byte says “raw byte-sized data,” while rune says “Unicode code point.”
var and :=.Floating-Point and Complex Types
Go’s two floating-point types are float32 and float64. When an untyped floating literal needs a default type, Go normally chooses float64.
var efficiency float64 = 17.5
voltage := 12.25 // inferred floating type in this context
Go also includes complex64 and complex128 for complex-number arithmetic. These are less common in everyday backend programming but useful in scientific and signal-processing work.
Booleans Are Explicit
A bool can be true or false. Go does not generally treat integers or strings as automatically “truthy” or “falsy.” Conditions expect Boolean expressions.
online := true
hasAlarm := false
if online {
println("running")
}
This keeps control flow explicit. Instead of asking whether an integer happens to be nonzero, write the comparison you mean.
Strings Are Immutable Byte Sequences
A Go string is an immutable sequence of bytes. Source-code string literals commonly contain UTF-8 text, but indexing a string returns a byte, not necessarily a complete Unicode character.
model := "S21"
message := "hello"
fmt.Println(message[0]) // byte value for 'h'
Later string lessons will cover UTF-8, byte slices, rune iteration, slicing, and why len reports bytes rather than a count of user-perceived characters.
Go Does Not Silently Mix Numeric Types
Even when two numeric types can represent similar values, Go generally requires an explicit conversion before combining them.
var racks int32 = 8
var spare int64 = 2
// total := racks + spare // compile error
total := int64(racks) + spare
This can feel strict at first, especially if you come from languages that perform extensive implicit promotion. The benefit is that the conversion is visible in the source code.
Constants Are Not Ordinary Variables
Constants are declared with const and represent values that can be determined at compile time.
const MaxRacks = 128
const DefaultVoltage = 12.0
const Banner = "Go Systems Lab"
Constants may be typed or untyped. Untyped constants are unusually flexible because Go can give them a concrete type when the surrounding context requires one, as long as the value is representable.
const Limit = 100
var a int = Limit
var b int64 = Limit
var c float64 = Limit
The constant Limit is not repeatedly converted from an existing runtime int variable. It is an untyped constant whose value can be represented in each target type.
Multiple Assignment and Declaration
Go can declare or assign several variables in one statement:
var model, site string
var rackCount, spareCount int
model, site = "S21", "Tacoma"
rackCount, spareCount = 8, 2
Short declarations can also create several variables at once:
model, watts := "S21", 3500
Inside the same scope, a short declaration can reuse existing variables only when at least one non-blank variable on the left side is new. This rule appears frequently when functions return multiple values.
Inspect Types While Learning
The fmt package can show both values and types while you experiment:
package main
import "fmt"
func main() {
count := 128
efficiency := 17.5
online := true
model := "S21"
fmt.Printf("%v -> %T\n", count, count)
fmt.Printf("%v -> %T\n", efficiency, efficiency)
fmt.Printf("%v -> %T\n", online, online)
fmt.Printf("%v -> %T\n", model, model)
}
%v prints the value in a default format, while %T prints the Go type. This is a useful learning and debugging technique when studying inference.
Common Beginner Mistakes
- Using
:=at package scope: short declarations belong inside functions. - Assuming an uninitialized variable is undefined: Go gives it the type’s zero value.
- Expecting automatic numeric promotion: explicit conversions are commonly required.
- Confusing
bytewith a Unicode character:byteisuint8;runeisint32used for Unicode code points. - Assuming string indexing returns a character: indexing returns one byte.
- Treating constants exactly like variables: untyped constants have compile-time behavior that ordinary variables do not.
- Adding explicit types everywhere: use inference when it keeps the code clear, and annotations where they communicate an important requirement.
Practical Exercise
- Create a new Go file named
types.go. - Declare four variables with
varbut no initializer: oneint, onefloat64, onebool, and onestring. - Print their zero values.
- Create four more variables with
:=and inspect their inferred types using%T. - Declare one
byteand onerune, then print both their values and types. - Create an
int32and anint64, attempt to add them directly, observe the compiler error, then fix it with an explicit conversion. - Create an untyped constant and assign it to an
int,int64, andfloat64. - Run
go fmt types.go,go vet types.go, andgo run types.go.
Knowledge Check + Answers
- What happens if a Go variable has no explicit initializer? It receives the zero value for its type.
- Can
:=be used at package scope? No. - What is the zero value of
bool?false. - What is the zero value of
string? The empty string. - What is
bytean alias for?uint8. - What is
runean alias for?int32. - Does Go automatically add an
int32to anint64? No; an explicit conversion is required. - What does
%Tprint withfmt.Printf? The value’s Go type. - What is the difference between a typed and untyped constant? A typed constant already has a specific type; an untyped constant can receive a concrete type from context when representable.
- When is
varespecially useful? At package scope, when an explicit type matters, or when you intentionally want the zero value without an initializer.
Primary References
- The Go Programming Language Specification
- A Tour of Go — Variables
- A Tour of Go — Basic Types
- A Tour of Go — Zero Values
- A Tour of Go — Constants
Elementary Review
Go variables are never “empty” in the undefined sense. Declare them with var or, inside functions, with :=. If you omit the initializer, Go supplies the type’s zero value. Use integer and floating types deliberately, remember that byte and rune are integer aliases with useful semantic meaning, and treat constants as compile-time values rather than ordinary mutable storage.
Editor’s Note
This lesson uses a unique generated 1200×630 anime featured image and a separate official Go gopher body image. Three distinct programming videos are distributed across the lesson rather than stacked together. Standard responsive Gutenberg headings, paragraphs, lists, code, image, and embed blocks are used throughout; ordinary lesson prose is not placed inside bordered, shaded, card-style, callout, panel, or fixed-width text boxes.
BitcoinVersus.Tech content is provided for informational and educational purposes.

Leave a Reply