Embedding

We have reviewed two methods to extend packages in Go:

  • Composition
  • Use alternative names

There’s another way to extend the built-in data type with embedding, which is kinda similar to inheritance in Java.

Let’s refactor the myTreeNode code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
type myTreeNode struct {
*tree.Node //Embeddding by omitting node
}

func (myNode *myTreeNode) postOrder() {
if myNode == nil || myNode.Node == nil {
return
}

left := myTreeNode{myNode.Left}
right := myTreeNode{myNode.Right}
left.postOrder()
right.postOrder()
myNode.Print()
}

func main() {
root := myTreeNode{&tree.Node{Value: 3}}
root.Left = &tree.Node{}
root.Right = &tree.Node{5, nil, nil}
root.Right.Left = new(tree.Node)
root.Left.Right = tree.CreateNode(2)
fmt.Println("In Order")
root.Traverse()
fmt.Println("Post Order")
root.postOrder()
fmt.Println()
}

Run the code above, we got the same outputs:

1
2
3
4
5
6
7
8
9
10
11
12
In Order
0
2
3
0
5
Post Order
2
0
0
5
3

Shadowed Method

We could “overload” the Traverse method in entry.go file

1
2
3
func (myNode *myTreeNode) Traverse(){
fmt.Println("This is a shadow method")
}

When we invoke the Traverse method, it will output the overloaded method:

1
2
3
4
5
6
7
8
In Order
This is a shadow method
Post Order
2
0
0
5
3

To invoke the original method, we should use root.Node.Traverse() instead.

Compared to composition method, using embedding is a syntax candy which can save lines of code.