Like most systems languages, Go provides a rich set of built-in primitive types: integers, floats, booleans, and strings. However, writing idiomatic Go requires understanding how literals behave, how the compiler treats untyped constants, and how zero-values work.
Zero Values
In Go, there is no such thing as an uninitialized or undefined variable. If you declare a variable without assigning an explicit value, Go automatically assigns it the zero value of its type:
- Numbers (
int,float64, etc.):0 - Booleans:
false - Strings:
""(empty string) - Pointers, slices, maps, channels, interfaces:
nil
var count int // 0
var enabled bool // false
var label string // ""
Chunk 2: Literals (Integers, Floats, Runes & Strings)
Literals
A literal is an explicit value written directly into your code.
1. Integer Literals
By default, integer literals are base 10. You can express other number bases using prefixes:
- Binary:
0b1010(10) - Octal:
0o12or012(10) - Hexadecimal:
0x1f(31)
To make large numbers readable without counting digits manually, Go supports underscores as digit separators:
const oneMillion = 1_000_000
const bytes = 0b1011_0101
Rule: Underscores cannot be placed at the start or end of an integer literal, and you cannot place two underscores consecutively.
2. Floating-Point Literals
Floating-point literals default to float64 when inferred. They can be written as decimals or using scientific (exponential) notation:
ratio := 3.14 // float64
largeVal := 2.5e3 // 2.5 * 10^3 = 2500
smallVal := 3.14e-2 // 3.14 * 10^-2 = 0.0314
3. Rune Literals
In Go, characters are called runes (an alias for int32 representing a Unicode code point). Runes are surrounded by single quotes ('), while strings use double quotes (") or backticks (`). They are not interchangeable.
Runes can be written as:
- Single Unicode character:
'a' - 8-bit octal:
'\141' - 8-bit hexadecimal:
'\x61' - 16-bit Unicode:
'\u0061' - 32-bit Unicode:
'\U00000061'
Common escape sequences:
\nβ New line\tβ Tab\\β Literal backslash\'β Single quote
4. String Literals
Go provides two ways to write strings:
Interpreted Strings ("...")
Surrounded by double quotes. They evaluate escape characters:
msg := "Hello\nWorld" // Creates a new line between Hello and World
Interpreted strings cannot span multiple lines in your source code.
Raw Strings (`...`)
Surrounded by backticks. They ignore escape sequences and preserve newlines:
query := `
SELECT id, name
FROM users
WHERE active = true;
`
Raw strings are great for multiline text, SQL queries, regex patterns, and JSON payloads.
The Magic of Literals & Variable Declarations
Go has two primary ways to declare variables:
// 1. Explicit declaration
var s string = "Hello"
// 2. Short declaration (inferred)
s := "Hello"
Untyped literals have arbitrary precision until assigned. Go evaluates literal arithmetic at compile-time and infers the correct type:
x := 1 + 0.5 // Automatically evaluated and inferred as float64
However, once a variable has a concrete type, Go strictly prohibits implicit conversion:
var a int = 10
var b float64 = 2.5
// Error: mismatched types int and float64
// result := a + b
// Valid: must convert explicitly
result := float64(a) + b
Division Edge Cases
The Go runtime handles zero-division differently depending on the types:
- Integer division by zero: Causes an immediate runtime panic (crash):
val := 10 / 0 // panic: runtime error: integer divide by zero - Floating-point division by zero: Does not crash; instead, it returns
+Inf,-Inf, orNaN(Not a Number):fmt.Println(1.0 / 0.0) // +Inf fmt.Println(-1.0 / 0.0) // -Inf fmt.Println(0.0 / 0.0) // NaN
Strict Booleans
Unlike C, Python, or JavaScript, Go booleans are strictly bool (true or false). Integers or strings cannot be treated as truthy or falsy:
// Invalid in Go:
// if 1 { ... }
// if "text" { ... }
// Valid:
isValid := true
if isValid {
// ...
}
Constants: Typed vs. Untyped
Constants are declared using const and must be known at compile time:
// Untyped constant: can be assigned to any compatible numeric type
const f = 9
var a int = f
var b float64 = f
// Typed constant: strictly locked to float64
const typedF float64 = 9
// var c int = typedF // Error: cannot use typedF (type float64) as type int
The βNo Wasteβ Rule
Go strictly enforces clean code at compile time:
- Local variables: If you declare a variable inside a function and do not use it, the compiler throws an error and will refuse to compile. This prevents dead code and forgotten variables.
- Package-level variables: Unused package-level variables are permitted by the compiler, though considered bad practice.
- Constants: Unused constants are always allowed. Since constants are evaluated during compilation, unused constants are simply stripped from the final binary with zero runtime performance cost.