Chapter 15: Go Data Types
Go Data Types — which usually means the full picture of types in Go, not just the primitives.
In most tutorials (especially “A Tour of Go” style, W3Schools, GeeksforGeeks, YouTube beginner series), “Go Data Types” covers:
- Basic / Built-in / Predeclared types (what we did last time)
- Composite / Derived / Aggregate types (the ones you build yourself or from basics)
Today let’s do the complete overview like a patient human teacher — from the official spec (go.dev/ref/spec#Types, updated Jan 2026 for Go 1.26) + Tour of Go (go.dev/tour/basics/11 and moretypes section).
We’ll go group by group, with tables, zero values, declaration examples, when to choose which, common mistakes, and runnable code you can try right now.
1. Overview — All Categories of Types in Go (2026)
Go has two big families:
- Predeclared / Basic types (built-in, no need to define)
- Composite types (constructed from other types)
| Category | Examples | Defined with keyword | Zero value example | Most common? |
|---|---|---|---|---|
| Basic / Numeric | bool, int, float64, string, byte, rune | — | false, 0, “”, nil | Very high |
| Composite — Array | [5]int | [size]T | all elements zero | Medium |
| Composite — Slice | []int | []T | nil | Extremely high |
| Composite — Struct | struct { Name string; Age int } | struct { … } | fields zero | Very high |
| Composite — Pointer | *int | *T | nil | High |
| Composite — Function | func(int) string | func(…) … | nil | High |
| Composite — Interface | interface { String() string } | interface { … } | nil | Very high |
| Composite — Map | map[string]int | map[K]V | nil | Extremely high |
| Composite — Channel | chan int | chan T | nil | Medium–high |
2. Quick Recap — Basic / Predeclared Types (Primitives)
(We covered these last time — just the table for reference)
| Type family | Types | Zero value | Typical size | Recommendation / Notes |
|---|---|---|---|---|
| Boolean | bool | false | 1 byte | — |
| Signed integer | int, int8, int16, int32, int64 | 0 | 8/16/32/64 bit | Use int most times |
| Unsigned integer | uint, uint8, uint16, uint32, uint64, uintptr | 0 | same | uint for sizes, byte = uint8 |
| Floating point | float32, float64 | 0.0 | 4/8 bytes | Always prefer float64 |
| Complex | complex64, complex128 | 0+0i | 8/16 bytes | Rare outside math |
| String | string | “” | — | Immutable UTF-8 bytes |
| Aliases | byte (= uint8), rune (= int32) | 0 | 1 / 4 bytes | Use byte for raw data, rune for Unicode chars |
Example recap:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
var ( ok bool = true count int = 42 pi float64 = 3.14159 name string = "Webliance" letter byte = 'G' emoji rune = '🚀' ) |
3. Composite Types — The Real Power (Where Go Shines)
These are the types you actually build most programs with.
a) Arrays — Fixed-size collections
- Size part of the type → [5]int ≠ [6]int
- Zero value: all elements zero-valued
|
0 1 2 3 4 5 6 7 8 9 10 |
var scores [5]int // [0,0,0,0,0] days := [7]string{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"} fmt.Printf("Days: %v (length: %d)\n", days, len(days)) // Days: [Sun Mon Tue Wed Thu Fri Sat] (length: 7) |
Rarely used directly — most people prefer slices.
b) Slices — Dynamic views on arrays (Most used collection!)
- Reference type → nil zero value
- Very flexible: append, slicing, capacity
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
var empty []int // nil slice (zero value) numbers := []int{10, 20, 30} // slice literal more := make([]int, 0, 10) // len=0, cap=10 more = append(more, 40, 50) fmt.Printf("numbers: %v (len=%d, cap=%d)\n", numbers, len(numbers), cap(numbers)) // numbers: [10 20 30] (len=3, cap=3) |
c) Structs — Custom record types (like classes without methods yet)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
type Person struct { Name string Age int Height float64 Active bool } var p Person // zero value: Name="", Age=0, Height=0.0, Active=false p2 := Person{ Name: "Webliance", Age: 25, Height: 175.5, } fmt.Printf("%+v\n", p2) // {Name:Webliance Age:25 Height:175.5 Active:false} |
d) Pointers — *T (address of something)
|
0 1 2 3 4 5 6 7 8 9 10 |
x := 42 p := &x // p has type *int *p = 100 // change x through pointer fmt.Println(x) // 100 |
e) Maps — Hash tables (key → value)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
m := make(map[string]int) m["apple"] = 5 m["banana"] = 3 value, ok := m["orange"] // ok = false if missing fmt.Printf("apple: %d, orange exists? %t\n", m["apple"], ok) |
f) Channels — For concurrency (Go’s superpower)
|
0 1 2 3 4 5 6 7 8 9 |
ch := make(chan string) go func() { ch <- "Hello from goroutine!" }() msg := <-ch fmt.Println(msg) |
4. Quick Reference Table — Zero Values & Nilability
| Type category | Zero value | Is nil possible? | Can be compared with == ? |
|---|---|---|---|
| bool, numeric, string | false / 0 / 0.0 / “” | No | Yes |
| Pointer, slice, map, channel, function, interface | nil | Yes | Yes (only nil == nil) |
| Array, struct | zero of each field/element | No | Yes (deep equality) |
5. Your Practice Task Right Now
Create data_types.go and mix everything:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package main import "fmt" type Student struct { Name string Grades []int } func main() { var s Student fmt.Printf("Zero student: %+v\n", s) scores := []int{85, 92, 78} web := Student{Name: "Webliance", Grades: scores} m := map[string]Student{"web": web} fmt.Printf("Grades of %s: %v\n", m["web"].Name, m["web"].Grades) } |
Run → see zero values + composite nesting.
Questions now?
- Deep dive on slices (append vs copy, capacity tricks)?
- Struct embedding vs inheritance?
- When to use pointer receivers?
- Or next: type conversions? interfaces? methods?
Keep running code — you’re turning into a real Go pro one concept at a time! 💪🇮🇳 Let’s keep it going! 🚀
