Ever written something like this in Go?
var a Animal = Dog{Name: "Charlie"} fmt.Println(a.Name) // 💥 compile-time error
...and thought, “Wait — why can’t I access Name
when it’s clearly part of the struct?”
🔍 Why This Happens
In Go, interfaces are contracts, not containers for struct fields. They only guarantee access to methods, not fields. So when you assign a struct to an interface, Go stores it as a hidden value — only accessible if you:
- Know the underlying type
- Use type assertion, or
- Use reflection
🧪 Real-World Example: API Payload
Let’s say you’re writing an API handler that receives some payload:
type User struct { Name string Email string } func (u User) IsValid() bool { return u.Email != "" } type Payload interface { IsValid() bool }
Now in your handler:
func Handle(p Payload) { fmt.Println(p.IsValid()) // ✅ fine fmt.Println(p.Name) // ❌ compile error }
Yep — Go won’t let you access p.Name
. Because Payload
doesn’t know Name
exists.
✅ Solution: Type Assertion
You can safely access the struct’s fields if you assert its type:
if u, ok := p.(User); ok { fmt.Println(u.Name) // 🎯 works! }
Or if you’re not sure of the type, use a type switch:
switch v := p.(type) { case User: fmt.Println(v.Name) default: fmt.Println("Unknown type") }
⚠️ Or... Use Reflection (Carefully)
You can also access struct fields dynamically via reflect
, like:
val := reflect.ValueOf(p) field := val.FieldByName("Name") fmt.Println(field.String())
But reflection can be tricky and error-prone. Use it only when you can’t use static typing — like dynamic JSON decoding or generic form handlers.
✨ Conclusion
Go’s strict typing can feel limiting at first, but it protects you from a whole class of bugs. Once you understand interfaces don’t “carry” struct fields — just methods — it all starts to click.
Want to go deeper? I shared the full breakdown with code samples and reflection examples here:
👉 Read the full post on Medium
Have you ever hit this issue in a real project? How did you work around it? Let’s chat below 👇
Top comments (0)