Regardless of whether is this an idiomatic go or not, in some situations we want to access an underlying concrete value of an interface value. here is an example:
I have these structs and interface:
type person struct {
name string
age int
}
type secretAgent struct {
name string
age int
}
type Human interface {
speak()
}
func (p person) speak() {}
func (p secretAgent) speak() {}
And I also have this function:
func bar(h Human) {
fmt.Println(h.name, "is sent to bar!!") // <-- name is not accessible
}
p1 := person{"foo bar", 34}
bar(p1)
How can I access struct fields in this situation?
CodePudding user response:
An interface is just a collection of methods.
Add a method to retrieve the name to it:
type Human interface {
speak()
name() string
}
func (p person) speak() {}
func (p person) name() string { return p.name }
func (p secretAgent) speak() {}
func (p secretAgent) name() string { return p.name }
func bar(h Human) {
fmt.Println(h.name(), "is sent to bar!!") // <-- name is now accessible
}
CodePudding user response:
For any one who might be interesting it this question, I found the solution.
Regardless of whether is this an idiomatic go or not, because interface can't find the exact type you are trying to access through it, you should assert the type of interface value.
A type assertion provides access to an interface value's underlying concrete value.
so in my case the implementation would be like this:
func bar(h Human) {
switch h := h.(type) { // <-- this is type assertion
case person:
fmt.Println(h.name, "is sent to bar!!") // <-- just has access to person
case secretAgent:
fmt.Println(h.name, "is sent to bar!!") // <-- has access to secretAgent
}
}