Note: THIS IS NOT A TUTORIAL!!! This blog is filled with my unfiltered, unverified thoughts. Read at your own risk!
Welcome to Part 2 of my journey learning Go! After working through flow control, I moved on to the next major section of the Go Tour: More types: structs, slices, and maps, along with function closures.
Part 1 was a bit of a syntax shock, but Part 2 was a serious mental workout. Here is the raw, unedited experience of how I navigated these data structures and functions.
1. Structs and Pointers
Coming from TypeScript, my first instinct was to compare Go's structs to interfaces or object shapes. But instantiating them felt completely alien to me:
type Vertex struct {
X int
Y int
}
v := Vertex{1, 2}
Declaring Vertex{1, 2} to instantiate it felt a bit unusual, but it makes sense once you realize it's like a blueprint.
What really boggled my mind, though, was pointer indirection. Look at this:
v := Vertex{1, 2}
p := &v
p.X = 1e9
In many lower-level languages, if p is a pointer to a struct, you can't just write p.X. You have to explicitly dereference it first (like (*p).X). But Go automatically handles that dereference for you. It's a remarkably convenient feature, even if it feels a bit like hack at first.
Another thing that threw me off was the output of fmt.Println(p). I fully expected it to print a raw, scary hexadecimal memory address. Instead, it printed &{1000000000 2}. I realized the fmt package automatically formats pointers to structs nicely for us behind the scenes. Thanks, Go!

2. Arrays vs. Slices (and Python Flashbacks)
My jaw dropped when I saw Go's array syntax:
var a [2]string
Wait... we have to specify the exact length of the array in its type? That felt incredibly rigid to me, and it made me wonder why anyone would ever choose to use arrays over anything else available, like, bro.

But then, the tour introduced slices. The syntax immediately gave me Python flashbacks:
primes := [6]int{2, 3, 5, 7, 11, 13}
var s []int = primes[1:4] // Just like Python slicing!
You can even use slice defaults like s[:2] or s[1:].
However, there is a catch that I'll have to keep an eye on to avoid bugs down the road: Slices are references to arrays. If you have multiple slices pointing to the same underlying array, changing an element in one slice changes the underlying array, which in turn updates all the other slices:
names := [4]string{"John", "Paul", "George", "Ringo"}
a := names[0:2] // [John Paul]
b := names[1:3] // [Paul George]
b[0] = "XXX"
// Now 'names' is [John XXX George Ringo]!
// 'a' also amazingly becomes [John XXX]!
This is incredibly efficient because Go isn’t copying data behind the scenes, but it's a behavior that could easily bite you if you aren't paying attention.

I also had to spend some time wrapping my head around the difference between a slice's length (how many elements are in it) and its capacity (how many elements are in the underlying array, starting from the slice's first element). Go's built-in make function makes dynamically allocating these slices super clean, but I'm still getting used to visualising how capacity behaves when you slice from the left.
3. Maps and the Sweet Taste of Victory
Next up were maps (associative arrays/dictionaries). Declaring them with var m map[string]Vertex was another syntax hurdle, but I loved how clean map literals look. Especially when you omit the redundant type names:
var m = map[string]Vertex{
"Bell Labs": {40.68433, -74.39967}, // Look, no explicit 'Vertex' type needed!
"Google": {37.42202, -122.08408},
}
At the end of the map section, I was faced with the WordCount Exercise. The goal was to write a function that counts the occurrences of each word in a string.
I sat down, wrote out the logic using strings.Fields, and... it passed on the very first try without me looking up a single thing!
Literally me when I crushed the exercise: 
Don't blame me though, because after struggling to adjust to Go's strict rules, having that solution compile and run perfectly was incredibly rewarding. It was the exact motivation boost I needed.
4. Closures and the Fibonacci Brain Melt
Just when I was feeling confident, Go introduced function closures.
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
This pattern really twisted my brain. I had a major question: How does sum := 0 not reset to 0 every time we call the function?
I lowkey kinda lost hope in this part, not gonna lie.

My "Aha!" Moment on Closures:
If you are confused by this too, here is the secret: When we write pos := adder(), we are calling adder() only once. This sets up a local variable sum = 0 in memory and returns the inner helper function.
When we subsequently call pos(1), pos(2), etc., we are calling that inner function directly. We are not calling adder() again. The inner function is "bound" to the specific environment where it was created, meaning it remembers and updates the exact same sum variable in memory between calls!
The Fibonacci Closure Challenge
To test this, the tour asked me to implement a Fibonacci generator using a closure. It took me three separate iterations to get it right. Seeing my thought process evolve shows just how tricky this was:
- Iteration 1 (The Overcomplicated Mess): I was trying to manage
curr,prev, andsumall at once while fighting the initial conditions of0and1. It worked but it did not work as well.
Target Output:
0 1 1 2 3...Actual Output:
0 1 2 3 5...
- Iteration 2 (Slightly cleaner, but wrong sequence): I tried to simplify it, but my sequence order was slightly off.
Target Output:
0 1 1 2 3...Actual Output:
1 2 3 5 8...
- Iteration 3 (The Elegant But Poorly-Written Solution):
func fibonacci() func() int {
curr := 1
prev := 0
return func() int {
sum := prev + curr
returnee := prev
prev = curr
curr = sum
return returnee
}
}
This third iteration worked perfectly! By capturing returnee := prev before modifying our state variables, the closure safely advances the Fibonacci sequence while returning the correct historical number.
Final Thoughts
This section of the tour was definitely a steep climb. Slices, pointers, and closures forced me to think much more about memory layout and variable scope than I usually do in JavaScript or Python.
But as the saying goes, "no pain, no gain." I'm currently facing the repercussions of adding a new wrinkle to my brain. HMU tho while I recover 😉
