You can also add methods to struct types using a method receiver. A method EmpInfo is added to the Employee struct.
In Go language, you are allowed to create a method with non-struct type receiver as long as the type and the method definitions are present in the same package. If they present in different packages like int, string, etc, then the compiler will give an error because they are defined in different packages. Example: Go.
In Go, we can define new types by using the following form. In the syntax, type is a keyword. New type names must be identifiers. But please note that, type names declared at package level can't be init .
As the compiler mentions, you can't extend existing types in another package. You can define your own alias or sub-package as follows:
type MyRouter mux.Router
func (m *MyRouter) F() { ... }
or by embedding the original router:
type MyRouter struct {
*mux.Router
}
func (m *MyRouter) F() { ... }
...
r := &MyRouter{router}
r.F()
I wanted to expand on the answer given by @jimt here. That answer is correct and helped me tremendously in sorting this out. However, there are some caveats to both methods (alias, embed) with which I had trouble.
note: I use the terms parent and child, though I'm not sure that is the best for composition. Basically, parent is the type which you want to modify locally. Child is the new type that attempts to implement that modification.
type child parent
// or
type MyThing imported.Thing
type child struct {
parent
}
// or with import and pointer
type MyThing struct {
*imported.Thing
}
You can see this in the following code.
working example on the playground
package main
import (
"fmt"
)
type parent struct {
attr string
}
type childAlias parent
type childObjParent struct {
parent
}
type childPointerParent struct {
*parent
}
func (p *parent) parentDo(s string) { fmt.Println(s) }
func (c *childAlias) childAliasDo(s string) { fmt.Println(s) }
func (c *childObjParent) childObjParentDo(s string) { fmt.Println(s) }
func (c *childPointerParent) childPointerParentDo(s string) { fmt.Println(s) }
func main() {
p := &parent{"pAttr"}
c1 := &childAlias{"cAliasAttr"}
c2 := &childObjParent{}
// When the parent is a pointer it must be initialized.
// Otherwise, we get a nil pointer error when trying to set the attr.
c3 := &childPointerParent{}
c4 := &childPointerParent{&parent{}}
c2.attr = "cObjParentAttr"
// c3.attr = "cPointerParentAttr" // NOGO nil pointer dereference
c4.attr = "cPointerParentAttr"
// CAN do because we inherit parent's fields
fmt.Println(p.attr)
fmt.Println(c1.attr)
fmt.Println(c2.attr)
fmt.Println(c4.attr)
p.parentDo("called parentDo on parent")
c1.childAliasDo("called childAliasDo on ChildAlias")
c2.childObjParentDo("called childObjParentDo on ChildObjParent")
c3.childPointerParentDo("called childPointerParentDo on ChildPointerParent")
c4.childPointerParentDo("called childPointerParentDo on ChildPointerParent")
// CANNOT do because we don't inherit parent's methods
// c1.parentDo("called parentDo on childAlias") // NOGO c1.parentDo undefined
// CAN do because we inherit the parent's methods
c2.parentDo("called parentDo on childObjParent")
c3.parentDo("called parentDo on childPointerParent")
c4.parentDo("called parentDo on childPointerParent")
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With