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 👇