I have code that has following structure:
// $GOPATH/experiments/interfaceexport/printer/printer.go
package printer
import "fmt"
type ResourcePrinter interface {
PrintSomething()
}
type JSONPrinter struct {
IsGeneric bool
}
func (printer *JSONPrinter) PrintSomething() {
fmt.Println("JSON")
}
// $GOPATH/experiments/interfaceexporter/printerretriever/printerretriever.go
package printer
import "experiments/interfaceexporter/printer"
func GetPrinter() printer.ResourcePrinter {
return &printer.JSONPrinter{IsGeneric: true}
}
// $GOPATH/experiments/interfaceexport/main.go
import "experiments/intefaceexport/printerretriever"
func main() {
printer := printerretriever.GetPrinter()
printer.PrintSomething() // "JSON"
// interfaceexport/main.go:13: printer.IsGeneric undefined (type printer.ResourcePrinter has no field or method IsGeneric)
if printer.IsGeneric {
printer.PrintSomething()
}
}
When I do go run main.go
I get following error:
interfaceexport/main.go:13: printer.IsGeneric undefined (type printer.ResourcePrinter has no field or method IsGeneric)
Why do I get above error even though IsGeneric
is exported?
printer.ResourcePrinter
is an interface, not the actual instance JSONPrinter, which does have access to IsGeneric
You would need to add a method IsGeneric()
to your interface (and implement it in JSONPrinter
) in order to be able to use that interface as you want.
See "golang how to access interface fields": you could also extract the dynamic value held by the interface variable through a type assertion:
dynamic_value := printer.(JSONPrinter)
Then dynamic_value
would have access to the IsGeneric
attribute.
See more at "How to access attribute of interface".
Even though compiler knows that
printer.ResourcePrinter
is an interface, it says thatIsGeneric
could also be a field.
The dynamic value of the interface can have field (see "Get all fields from an interface")
The no field part, when applied to an interface, can refer to an embedded type, the unqualified type’s name acts as the field name.
type ReadWriter interface {
Read(b Buffer) bool
Write(b Buffer) bool
}
type File interface {
ReadWriter // same as adding the methods of ReadWriter
Locker // same as adding the methods of Locker
Close()
}
You also see that kind of error message when using a pointer to an interface (when the interface itself includes a pointer of sorts: "Go: What's the meaning of interface{}
?" and "Cast a struct pointer to interface pointer in Golang")
See issue 10700
When using a new, unfamiliar package, programmers occasionally make the error of using a pointer to an interface type instead of the interface type directly.
Simple, your interface has no method IsGeneric
:
type ResourcePrinter interface {
PrintSomething()
}