Types and Variables
Integer Types
Section titled “Integer Types”Go provides signed and unsigned integers at standard widths:
| Type | Size (bytes) | Range (signed) | Range (unsigned) |
|---|---|---|---|
int8 / uint8 | 1 | -128 to 127 | 0 to 255 |
int16 / uint16 | 2 | -32,768 to 32,767 | 0 to 65,535 |
int32 / uint32 | 4 | -2,147,483,648 to 2,147,483,647 | 0 to 4,294,967,295 |
int64 / uint64 | 8 | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | 0 to 18,446,744,073,709,551,615 |
int / uint | 4 or 8 | Same as int32 or int64 (platform-dependent) | Same as uint32 or uint64 |
uintptr | 4 or 8 | Unsigned integer large enough to store a pointer value |
int and uint are the default integer types. Their size matches the native word size of the Platform: 32 bits on 32-bit systems, 64 bits on 64-bit systems. Use int unless you need a specific Size.
var x int = 42var y int64 = 42Integer Overflow
Section titled “Integer Overflow”Go integers wrap around on overflow in the same manner as two”s complement arithmetic. The compiler Does not insert runtime checks:
var x uint8 = 255x += 1 // x == 0 (wraps)Use math/bits for explicit overflow detection:
a, carry := bits.Add(255, 1, 0) // a == 0, carry == 1Floating-Point Types
Section titled “Floating-Point Types”| Type | Size | Precision |
|---|---|---|
float32 | 4 bytes | ~6-7 decimal digits |
float64 | 8 bytes | ~15-16 decimal digits |
float64 is the default. Both conform to IEEE 754.
x := 3.14 // float64var y float32 = 2.71IEEE 754 gotchas apply identically to Go as to other languages:
fmt.Println(0.1 + 0.2 == 0.3) // falsefmt.Println(math.Abs(0.1+0.2-0.3) < 1e-15) // truemath.NaN() exists. NaN does not compare equal to anything:
nan := math.NaN()fmt.Println(nan == nan) // falsefmt.Println(math.IsNaN(nan)) // trueBoolean Type
Section titled “Boolean Type”bool is one byte. No implicit conversion to/from integers.
var b bool = truefmt.Println(b) // truefmt.Println(!b) // falseString Type
Section titled “String Type”Strings are immutable sequences of UTF-8 bytes. They are not null-terminated and their length is Stored explicitly. The zero value is ""Not nil.
s := "hello"fmt.Println(len(s)) // 5 (byte length)fmt.Println(s[0]) // 104 (byte value of 'h')fmt.Println(string(s[0])) // "h"String indexing yields bytes, not runes. Use for range for character iteration:
s := "hello"for i, r := range s { fmt.Printf("%d: %c\n", i, r)}Multi-byte UTF-8:
s := "日本語"fmt.Println(len(s)) // 9 bytes (3 chars x 3 bytes)fmt.Println(utf8.RuneCountInString(s)) // 3 runesString concatenation with + allocates a new string. For many concatenations, use strings.Builder:
var sb strings.Builderfor _, s := range items { sb.WriteString(s)}result := sb.String()Zero Values
Section titled “Zero Values”Every type in Go has a zero value. Variables declared without an explicit initializer are set to Zero. This eliminates uninitialized variable bugs.
| Type | Zero Value |
|---|---|
int | 0 |
float64 | 0.0 |
bool | false |
string | "" |
| Pointer | nil |
| Slice | nil |
| Map | nil |
| Channel | nil |
| Interface | nil |
| Struct | All fields set to their zero values |
| Array | All elements set to their zero values |
var x intvar s stringvar p *intfmt.Println(x, s, p) // 0 <nil>Variable Declaration
Section titled “Variable Declaration”var x int = 42var y = 42 // type inferredvar a, b int = 1, 2var ( name string = "go" age int = 15)Short declaration (:=)
Section titled “Short declaration (:=)”Inside functions only. Type is inferred from the right-hand side.
func main() { x := 42 s := "hello" fmt.Println(x, s)}:= cannot be used at package level. It is syntactic sugar for var with type inference.
new(T) allocates a zeroed value of type T and returns a pointer *T.
p := new(int)fmt.Println(*p) // 0*p = 42fmt.Println(*p) // 42Constants
Section titled “Constants”Constants are declared with const. They must be computable at compile time.
const Pi = 3.14159const Greeting = "hello"
const ( StatusOK = 200 StatusErr = 500)
// iota generates sequential integersconst ( A = iota // 0 B // 1 C // 2)iota is a predeclared identifier that resets to 0 in each const block and increments by one for Each subsequent constant. It enables bit flag and enumeration patterns:
const ( FlagRead = 1 << iota // 1 FlagWrite // 2 FlagExec // 4)
const ( _ = iota // 0, discarded KB = 1 << (10 * iota) // 1024 MB // 1048576 GB // 1073741824)Type Conversions
Section titled “Type Conversions”Go requires explicit conversions between types. There are no implicit numeric conversions.
var i int = 42var f float64 = float64(i)var u uint = uint(i)Numeric conversions that lose precision truncate:
var x int64 = 300var y int8 = int8(x) // 44 (300 mod 256, wraps)String conversions:
b := []byte("hello") // string to byte slices := string([]byte{104, 101}) // byte slice to string
i := 42s := strconv.Itoa(i) // "42"j, _ := strconv.Atoi("42") // 42Safe Conversions
Section titled “Safe Conversions”There is no built-in safe conversion that returns an error. Use explicit bounds checks:
func safeUint64(n int64) (uint64, bool) { if n < 0 { return 0, false } return uint64(n), true}Type Aliases
Section titled “Type Aliases”type Celsius float64type Fahrenheit float64
func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32)}type creates a new, distinct type. Celsius and float64 are different types — you must convert Explicitly. This prevents accidentally mixing incompatible values.
Since Go 1.9, type aliases (using =) create an alias, not a new type:
type Byte = bytetype Rune = int32Intuition
Section titled “Intuition”Types are labeled boxes in a warehouse: Think of Go’s type system as a warehouse where every item sits in a labeled box. You can’t pour water into a box labeled “sand” — Go forces you to explicitly relabel (convert) before moving data between boxes. Zero values mean every box starts with something reasonable inside, so you never open an empty box by accident.
Why it matters: Explicit type conversions catch entire classes of bugs at compile time rather than letting silent truncation or reinterpretation corrupt data at runtime. The zero-value guarantee eliminates the “uninitialized variable” category of bugs entirely.
The key insight: Go trades a small amount of typing convenience for a large gain in correctness — every conversion is visible, every variable starts sane.
Common Pitfalls
Section titled “Common Pitfalls”Using
==to compare floats. IEEE 754 makes exact equality unreliable. Use an epsilon comparison:math.Abs(a-b) < epsilon.String indexing yields bytes.
s[i]returns abyteNot arune. For multi-byte UTF-8, this can split a character. Usefor i, r := range sfor rune iteration.Assuming
intis 64-bit. On 32-bit systems,intis 32 bits. Useint64explicitly when the value may exceed 2^31 - 1.:=in outer scope.:=in an inner block creates a new variable that shadows the outer one. Use=for assignment to an existing variable.nilslices vs empty slices. Anilslice has length and capacity 0 but is not equal to an empty slice ([]int{}). JSON marshaling treats them differently:nilbecomesnull``[]int{}becomes[].Integer overflow is silent. Unlike Rust (debug panics) or Python (arbitrary precision), Go wraps on overflow without any runtime error. Use
math/bitsor explicit checks when overflow is a concern.
Summary
Section titled “Summary”This topic covers the core concepts of types and variables, including underlying theory, practical implementation, and key applications.
Key concepts include:
- core concepts and terminology
- algorithms and computational thinking
- practical implementation
- security and ethical considerations
- applications in the real world
Understanding these concepts thoroughly is essential for both examinations and practical programming, and requires both theoretical knowledge and hands-on practice.
Worked Examples
Section titled “Worked Examples”Worked examples demonstrating the application of key concepts are covered in the detailed sub-pages linked above.
Cross-References
Section titled “Cross-References”- Arrays, Slices, and Maps: Collection types that build on scalar type foundations.
- Interfaces: Structural typing and interface satisfaction for custom types.
- Pointers and Memory: Pointer semantics and escape analysis for variable storage.