Consider the following Go code that creates an array and a linked list with the same integer values. What will be printed regarding the memory addresses?
package main import ( "fmt" ) type Node struct { value int next *Node } func main() { arr := [3]int{10, 20, 30} head := &Node{value: 10} head.next = &Node{value: 20} head.next.next = &Node{value: 30} fmt.Println("Array addresses:") for i := 0; i < len(arr); i++ { fmt.Printf("%p ", &arr[i]) } fmt.Println() fmt.Println("Linked list node addresses:") current := head for current != nil { fmt.Printf("%p ", current) current = current.next } fmt.Println() }
Think about how arrays and linked lists store their elements in memory.
Arrays store elements in contiguous memory locations, so their addresses are next to each other. Linked list nodes are allocated separately on the heap, so their addresses are scattered.
Which statement correctly describes the memory usage difference between an array and a linked list storing the same number of integer elements?
Consider what extra information each linked list node must store.
Each linked list node stores the element plus a pointer to the next node, which adds extra memory overhead. Arrays store elements contiguously without extra pointers, so they use less memory overall.
What happens to the memory layout of a Go slice when it grows beyond its capacity?
Consider this code snippet:
package main import ( "fmt" ) func main() { slice := make([]int, 3, 3) slice[0], slice[1], slice[2] = 1, 2, 3 fmt.Printf("Initial slice address: %p\n", &slice[0]) slice = append(slice, 4) fmt.Printf("After append slice address: %p\n", &slice[0]) }
Think about what happens when a slice exceeds its capacity.
When a slice exceeds its capacity, Go allocates a new larger array and copies the elements over. This new array is at a different memory location, so the address changes.
Why do linked lists have nodes stored at non-contiguous memory locations?
Think about how nodes are created and linked in memory.
Linked list nodes are allocated individually on the heap when needed, so their memory locations are scattered and not contiguous.
Given the following Go code, what will be the printed memory layout pattern?
package main import ( "fmt" ) type Node struct { val int next *Node } func main() { arr := []int{1, 2, 3} head := &Node{val: 1} head.next = &Node{val: 2} head.next.next = &Node{val: 3} fmt.Println("Array addresses before append:") for i := range arr { fmt.Printf("%p ", &arr[i]) } fmt.Println() arr = append(arr, 4) fmt.Println("Array addresses after append:") for i := range arr { fmt.Printf("%p ", &arr[i]) } fmt.Println() fmt.Println("Linked list node addresses:") current := head for current != nil { fmt.Printf("%p ", current) current = current.next } fmt.Println() }
Recall how Go slices grow and how linked list nodes are allocated.
Appending beyond capacity causes the slice to allocate a new underlying array at a new memory location, changing addresses. Linked list nodes remain individually allocated and scattered.
