32.7 When to Use Reflection and When to Avoid It

Look, let’s get one thing straight: reflection is like a fire axe behind glass that says “BREAK IN CASE OF EMERGENCY.” It’s an incredibly powerful tool that you should almost never use. The moment you reach for reflect, you’re saying, “I know the type system is there for a reason, but I’m going to ignore it for a bit.” It’s a deliberate step around the language’s safety features, and you’d better have a darn good reason for it.

32.6 The Laws of Reflection: Three Foundational Rules

Alright, let’s talk about the three rules that make reflection in Go actually work. Think of these not as suggestions, but as the fundamental physics of the reflect package. If you ignore them, your code will blow up, and it will be a very confusing explosion. I’ve been there. It’s not pretty. These rules govern how Go values move between the ordinary world of int, string, and struct and the mirrored world of reflect.Value and reflect.Type. Master them, and you hold the power to metaprogram. Mess them up, and you’ll spend an hour wondering why a perfectly good value is suddenly “invalid.”

32.5 Setting Values via Reflection

Alright, let’s get our hands dirty. You’ve inspected a value, found a field or an element you want to change, and now you want to actually change it. This is where we move from passive observation to active intervention, and where things get… interesting. The reflect package gives us reflect.Value.Set(), and it looks deceptively simple. The catch? It’s one of the most pedantic, fussy functions in the entire standard library. It will refuse to work for the slightest reason, and its error messages are about as helpful as a screen door on a submarine.

32.4 Calling Methods and Functions Dynamically

Alright, let’s get our hands dirty with the real party trick: calling methods and functions you only know by name at runtime. This is where reflect stops being a fancy mirror and becomes a full-on remote control for your code. It’s powerful, it’s a bit dangerous, and it feels like you’re breaking the rules, even though you’re not. The core of this operation is the Value.Call method. But before you can Call anything, you need a reflect.Value representing the function itself. And crucially, that Value must be of Kind reflect.Func. If it’s not, you’re about to trigger a panic that will stop your program dead in its tracks. No gentle errors here; it’s the reflect package’s way of saying, “You should have known better.”

32.3 Reading Struct Tags with reflect

Right, so you’ve got a struct. It’s a nice, tidy little struct. You’ve probably adorned it with some backticked decorations, like json:"name" or db:"user_id". These struct tags are fantastic for configuration, but they’re just… there. They’re a part of the comment, essentially invisible to your running code. Until you bring in the big guns: the reflect package. Think of reflect as your all-access pass to the type system’s backstage. It lets you interrogate a type at runtime to figure out what it’s made of. And reading struct tags is one of its most common and practical party tricks. It’s how libraries like encoding/json know how to map your UserName field to a "user_name" key in JSON without you having to write a single line of parsing logic. Let’s break down how you can do that yourself.

32.2 Kinds: Distinguishing Structs, Slices, Maps, and Pointers

Alright, let’s get our hands dirty with reflect.Kind. This is where we move from the philosophical “what is a type?” to the practical “what the heck am I looking at right now?”. Think of a type’s Kind as its fundamental category. It’s the answer to the question, “Is this a struct? A slice? A pointer to a string? An obscure 16-bit integer?” While a reflect.Type describes the full blueprint (e.g., map[string][]*MyStruct), the Kind tells you the core building material (e.g., reflect.Map). This distinction is crucial because most of your reflection code will branch based on Kind.

32.1 reflect.Type and reflect.Value: Inspecting Types at Runtime

Right, so you’ve decided to play with fire. Good. Reflection in Go is exactly that: a powerful, dangerous tool that lets you reach into the guts of the language and muck about with types and values you only know about at runtime. It’s how you write code that writes code. It’s also how you create beautifully abstract, horrifyingly slow, and spectacularly panicky programs if you’re not careful. The entire reflect package orbits around two celestial bodies: reflect.Type and reflect.Value. You cannot do anything without one or both of these. Think of reflect.Type as the blueprint of a house and reflect.Value as the actual, physical house itself, complete with all the furniture (the data) inside.

— joke —

...