Golang composition
These are some notes I took while experimenting and playing around with Golang further. This article is mainly exploring embedded structs and interfaces to experiment how they work etc.
Use Golang playground in order to see how it works in action
One can combine golang interfaces together to form large interfaces.
package main
import (
"fmt"
)
type AAA interface {
Hahax()
}
type BBB interface {
Miao()
}
type CCC interface {
AAA
BBB
}
type ZZZ struct{}
func (z ZZZ) Hahax() {
fmt.Println("ZZZ Hahax")
}
func (z ZZZ) Miao() {
fmt.Println("ZZZ Miao")
}
func Printer(c CCC) {
c.Hahax()
c.Miao()
}
func main() {
z := ZZZ{}
Printer(z)
}
- Interface
CCCis formed from interfaceAAAandBBB - In order to fulfill requirements of
CCC, structZZZneeds to implement both theHahaxandMiaofunctions. - In order to understand where each function is being called from, we would have the function print out which struct it comes from and the name of its function.
The following code outputs the following
ZZZ Hahax
ZZZ Miao
We can take apart struct ZZZ and compose it from multiple structs instead
package main
import (
"fmt"
)
type AAA interface {
Hahax()
}
type BBB interface {
Miao()
}
type CCC interface {
AAA
BBB
}
type DD1 struct{}
func (z DD1) Hahax() {
fmt.Println("DD1 Hahax")
}
type DD2 struct{}
func (z DD2) Miao() {
fmt.Println("DD2 Miao")
}
type ZZZ struct {
DD1
DD2
}
func Printer(c CCC) {
c.Hahax()
c.Miao()
}
func main() {
z := ZZZ{}
Printer(z)
}
- Interface
CCCis formed from interfaceAAAandBBB - In order to fulfill requirements of
CCC, structZZZneeds to implement both theHahaxandMiaofunctions. - Struct
ZZZis composed of structsDD1andDD2.DD1implements theHahaxmethod whileDD2implements theMiaomethod - Similarly, in order to understand where each function is being called from, we would have the function print out which struct it comes from and the name of its function.
The following code would output the following:
DD1 Hahax
DD2 Miao
However, let’s experiment further. What if ZZZ which is already composed DD1 and DD2 (which fulfills the requirements of CCC) also implements the Hahax function?
package main
import (
"fmt"
)
type AAA interface {
Hahax()
}
type BBB interface {
Miao()
}
type CCC interface {
AAA
BBB
}
type DD1 struct{}
func (z DD1) Hahax() {
fmt.Println("DD1 Hahax")
}
type DD2 struct{}
func (z DD2) Miao() {
fmt.Println("DD2 Miao")
}
type ZZZ struct {
DD1
DD2
}
func (z ZZZ) Hahax() {
fmt.Println("ZZZ Hahax")
}
func Printer(c CCC) {
c.Hahax()
c.Miao()
}
func main() {
z := ZZZ{}
Printer(z)
}
The above code outputs the following instead.
ZZZ Hahax
DD2 Miao
Notice how as compared to previous situation, instead of printing out DD1 Hahax, it prints out ZZZ Hahax instead. So, there is some sort of level of hierarchy when functions are being called. If the list of function within that level has the Hahax function, it would call it; else, it would go down through the structs embedded within it and call it accordingly.
Now, let’s experiment further. What if DD2 does not implement the Miao function but instead, it embeds DD3 which then implements the Miao function?
package main
import (
"fmt"
)
type AAA interface {
Hahax()
}
type BBB interface {
Miao()
}
type CCC interface {
AAA
BBB
}
type DD1 struct{}
func (z DD1) Hahax() {
fmt.Println("DD1 Hahax")
}
type DD2 struct {
DD3
}
type DD3 struct{}
func (z DD3) Miao() {
fmt.Println("DD3 Miao")
}
type ZZZ struct {
DD1
DD2
}
func (z ZZZ) Hahax() {
fmt.Println("ZZZ Hahax")
}
func Printer(c CCC) {
c.Hahax()
c.Miao()
}
func main() {
z := ZZZ{}
Printer(z)
}
And as expected, the following code outputs the following:
ZZZ Hahax
DD3 Miao
Apparently, it would recurse down the embedded structs and use the first Miao function observed.
If somehow, DD1 also implements the Miao function, that it would it be expected that the DD3 Miao would not be printed but DD1 Miao would be printed instead.
package main
import (
"fmt"
)
type AAA interface {
Hahax()
}
type BBB interface {
Miao()
}
type CCC interface {
AAA
BBB
}
type DD1 struct{}
func (z DD1) Hahax() {
fmt.Println("DD1 Hahax")
}
func (z DD1) Miao() {
fmt.Println("DD1 Miao")
}
type DD2 struct {
DD3
}
type DD3 struct{}
func (z DD3) Miao() {
fmt.Println("DD3 Miao")
}
type ZZZ struct {
DD1
DD2
}
func (z ZZZ) Hahax() {
fmt.Println("ZZZ Hahax")
}
func Printer(c CCC) {
c.Hahax()
c.Miao()
}
func main() {
z := ZZZ{}
Printer(z)
}
The following is the output for this piece of code:
ZZZ Hahax
DD1 Miao
Let’s remove DD3 from the latest iteration of the code and also have DD2 also implement the Miao function. That would make it confusing - which Miao function should be used when since DD1 and DD2 embedded struct appear to be on the same level?
package main
import (
"fmt"
)
type AAA interface {
Hahax()
}
type BBB interface {
Miao()
}
type CCC interface {
AAA
BBB
}
type DD1 struct{}
func (z DD1) Hahax() {
fmt.Println("DD1 Hahax")
}
func (z DD1) Miao() {
fmt.Println("DD1 Miao")
}
type DD2 struct {}
func (z DD2) Miao() {
fmt.Println("DD2 Miao")
}
type ZZZ struct {
DD1
DD2
}
func (z ZZZ) Hahax() {
fmt.Println("ZZZ Hahax")
}
func Printer(c CCC) {
c.Hahax()
c.Miao()
}
func main() {
z := ZZZ{}
Printer(z)
}
We now have the following:
./prog.go:52:9: ZZZ.Miao is ambiguous
./prog.go:52:9: cannot use z (type ZZZ) as type CCC in argument to Printer:
ZZZ does not implement CCC (missing Miao method)
Even the golang runtime becomes unsure of which one to run and it panics.