6.7 Pointers and Garbage Collection: No Dangling Pointers

Right, let’s talk about one of the most brilliant and terrifying features of Go: its garbage collector and what it means for your pointers. You’ve probably come from a language where you had to constantly worry about free() or delete, meticulously pairing every malloc with its destruction like a morbid matchmaking service. In Go, we fire the matchmaker. The garbage collector (GC) is our cleanup crew, and it’s spectacularly good at its job.

6.6 Stack vs Heap: Escape Analysis and Where Values Live

Right, let’s talk about real estate. Not the kind with open houses and questionable wallpaper, but the kind your program cares about: where your values live. This isn’t just academic; it dictates who cleans up the mess, how fast things are, and whether you get a segfault at 2 AM. I need you to forget the “stack is fast, heap is slow” mantra for a second. It’s a symptom, not the cause. The real question is: why does the language put a value in one place or the other? The answer, in Go, isn’t you. At least, not entirely. You make requests with your code’s structure, and the compiler makes the final call using a brilliant process called escape analysis.

6.5 Why Go Has No Pointer Arithmetic

Right, so you’ve heard the horror stories. Pointer arithmetic in C is like giving a toddler a power drill: it’s incredibly effective for the one-in-a-million task it was designed for, and an absolute catastrophe for everything else. It’s the source of bugs so subtle and pernicious that they can take weeks to find, often only after your application has already mailed your entire customer database to a fax machine in Belarus.

6.4 new() vs &T{}: Two Ways to Allocate

Look, I get it. You’re staring at new(int) and &int{} and wondering if this is just another one of Go’s charmingly redundant features, like having two ways to declare a variable. Is it a coin toss? Absolutely not. While they can produce the same result in a simple case, they represent two fundamentally different philosophies of instantiation. One is a holdover, a blunt instrument; the other is the idiomatic, expressive way to bring a new struct into this cruel world.

6.3 Passing Pointers to Functions: Mutation Without Return

Right, so you’ve got a handle on getting a variable’s address with & and peeking inside it with *. Neat party tricks, but the real magic—the reason pointers become an absolute necessity—happens when you start passing them to functions. This is where we move from simply looking at data to actually commanding it from across the room. Think about it: in C, everything is pass-by-value. When you call a function and pass a variable, you’re not handing it the original variable; you’re handing it a copy. The function can mess with that copy all it wants, and your original data remains blissfully untouched. This is fine, even desirable, most of the time. But what if you want the function to change the original? You can’t return ten different values from one function, and that’s where we stop asking nicely and start handing out addresses.

6.2 nil Pointers and Safety Checks

Right, let’s talk about the void. The great nothing. The nil pointer. It’s the ghost in your machine, and if you don’t respect it, it will reach out and crash your entire program just to teach you a lesson. It’s not being malicious; it’s just brutally, unforgivingly logical. Think of a pointer as a slip of paper with an address written on it. A nil pointer is that same slip of paper, but instead of an address, it just has the word “NOWHERE” scrawled on it in big, angry letters. If I tell you, “Go to this address and water the plants,” and hand you that slip, you’d rightly look at me like I’m an idiot. You can’t water plants at “NOWHERE.” Your computer feels the same way. Asking it to dereference a nil pointer—to go to that non-existent address and get or set a value—is a fundamental error. It’s the SIGSEGV, the segmentation violation. The hardware itself raises a flag and says, “Absolutely not.”

6.1 Pointer Basics: & and * Operators

Alright, let’s get our hands dirty with the two operators that make pointers both powerful and infuriating: & (the address-of operator) and * (the dereference operator). If you don’t get these, you’ll be lost at sea without a paddle, and the sea is full of segmentation faults. Think of a variable in your code, say int score = 975;. It lives somewhere in your computer’s memory. That ‘somewhere’ is its address. The & operator is your way of asking, “Hey, variable, where do you live?” It gives you the memory address of the variable.

— joke —

...