I have two files, generic_handler.go, which essentially looks like this:
type Handler struct{
fields map[string]interface{}
}
func (handler *Handler) addField(key string, value interface{}){ some code }
And stat_handler.go:
type StatHandler Handler
When I try to call (from within the stat_handler.go file) the method like this, I get an error:
//inside some function
stathandler.addField("some field", "some value")
It errors out with type StatHandler has no field or method addField
. This is the same even if I export addField
by making it AddField
. Both of these files reside in the same package.
Is there something I am missing?
In Go you'd typically do this through composition:
type StatHandler struct {
Handler // Anonymous member of type Handler
}
// ...Later on
var stathandler StatHandler
stathandler.addField("some field", "some value")
Please be aware that in Go in order to access a method from another package you need to export it, meaning that you have to capitalize the first letter of the method.
type Handler struct{
fields map[string]interface{}
}
func (handler *Handler) AddField(key string, value interface{}){ some code }
Then if your package is named as stathandler
you can access the AddField
method as:
stathandler.AddField("some field", "some value")
A declared method belongs to a specific type. The type
keyword creates a new type which does not "inherit" methods of the type you used in the type specification.
The method addField()
you declared belongs to Handler
, the type StatHandler
does not have any methods because you haven't specified any methods with that as the receiver type.
If you have a variable of type StatHandler
and if you want to call the addField()
method, you need to have a value of type *Handler
. You may obtain such a value by using a type conversion, e.g.:
s := StatHandler{}
(*Handler)(&s).addField("somekey", "someval")
Note that since addField()
has pointer receiver, a pointer is required (hence the use of &
address operator), but then the *StatHandler
can only be converted to *Handler
.
If you would have an *StatHandler
pointer in the first place:
sp := &StatHandler{}
(*Handler)(sp).addField("somekey", "someval")
Since new types do not "inherit" methods of the underlying type, you should consider embedding to achieve what you want, because methods and fields of an embedded type are promoted to the embedder type:
type StatHandler struct {
Handler // Embed Handler, so addField() method will be promoted
}
s2 := StatHandler2{}
s2.addField("somekey", "someval")
Try the examples on the Go Playground.
The exact definition of what methods a type has is covered in the spec: Method sets.