function Mocking through Interface in golang - oop

I am trying to write a unit test code form following code which has 3 level of function calling as below:
The main function calls function A() and then function A calls function B() and C() depending upon some condition and function B calls function E() and F(), whereas function C calls function G() and H() on some condition.
The above like the code I have developed, Here I want to mock function E() and F() for function B, and G() and H() for function C. Please suggest me how to do it using interface.

Abstract function type
You can do it with dependency injection not using interfaces:
import (
"fmt"
"math"
)
type a func(float64) float64
func A(arg float64) float64 {
return math.Pow(arg, 2)
}
func mock(arg float64) float64 {
return math.Sqrt(arg)
}
func b(function a, arg float64) float64 {
return function(arg)
}
func main() {
fmt.Println(b(A, 2))
fmt.Println(b(mock, 2))
}
Function is first class citizen in Go
In programming language design, a first-class citizen (also type, object, entity, or value) in a given programming language is an entity which supports all the operations generally available to other entities.
It means you can pass function as argument among other possibilities. And of course you can declare an abstract type based on function with concrete interface (Don't confuse with interface type)
Interface approach
You can make compositions using your functions
import (
"fmt"
"math"
)
// Declare an interface type with dependencies
type HGer interface {
H(float64) float64
G(float64) float64
}
// Declare a dependent type with embedded interface
type Dependent struct {
HGer
}
func (d *Dependent) B(arg float64) float64 {
return d.H(arg) * d.G(arg)
}
// Implement the interface for an actual program
type ImplHGer struct{}
func (i *ImplHGer) H(arg float64) float64 {
return math.Pow(arg, 2)
}
func (i *ImplHGer) G(arg float64) float64 {
return math.Sqrt(arg)
}
// Implement the interface for mock of dependencies
type MockHGer struct{}
func (i *MockHGer) H(arg float64) float64 {
return float64(0)
}
func (i *MockHGer) G(arg float64) float64 {
return float64(0)
}
func main() {
// Use real implementation
a := Dependent{new(ImplHGer)}
// Use the mock
b := Dependent{new(MockHGer)}
fmt.Println(a.B(8)) // 181.01933598375618
fmt.Println(b.B(8)) // 0
}
Embedding
Including an anonymous field in a struct is known as embedding. In this case the Discount type is embedded in the PremiumDiscount type. All the methods of Discount are instantly available on the PremiumDiscount type. Furthermore those same methods can be hidden
It is possible to embed interface to struct to extend it's behavior or to be more specific - declare abstract dependency.

Related

How to implement an interface with functions sharing the same logic?

I'd like to provide multiple implementations for the following interface:
type API interface {
A()
B()
C()
}
According to my use cases, all implementations should share the exact same logic for function A and B while function C will have different logic for different implementations.
So I've created the following common implementation to be embedded:
type Common struct {}
func (c *Common) A() {}
func (c *Common) B() {}
To create two implementations for the interface above, I can just do the following:
type FirstImpl struct { Common }
func (i *FirstImpl) C() {}
type SecondImpl struct { Common }
func (i *SecondImpl) C() {}
Everything works just fine until I find out that function C needs to be called inside function B. Note that the logic for function B should still be the same across two implementations despite that we may get different results calling C inside B.
I'm wondering if this is a common pattern in Go and if there is an elegant way to handle it.
You want to emulate late binding.
One way to achieve this is by using a function pointer, and constructors for implementations:
type CommonImpl struct {
cimpl func()
}
func (c CommonImpl) C() { c.cimpl() }
type FirstImpl struct {
CommonImpl
}
func NewFirstImpl() APIImpl {
ret:=FirstImpl{}
ret.cimpl=ret.c
return &ret
}
With this implementation, you can call the derived-type C().
An alternative would be to pass the function as an argument:
func (c CommonImpl) C(bfunc func()) {
}
...
x:=FirstImpl{}
x.C(x.B)
Or with an interface:
type BIntf interface {
B()
}
func (c CommonImpl) C(b BIntf) {
}
x:=FirstImpl{}
x.C(x)

The "Builder-style usage of methods that return Unit" on Kotlin website confuse me

The Idioms section of the official Kotlin docs contains this example:
Builder-style usage of methods that return Unit
fun arrayOfMinusOnes(size: Int): IntArray {
return IntArray(size).apply { fill(-1) }
}
As the function apply returns the generic type, and I thought Unit is as same as void in Java, this section is suggesting we can use a void method in builder-style? That doesn't make sense to me - what's it trying to say?
The point it's trying to make is that if you just did traditional Java builder style, like this:
return IntArray(size)
.fill(-1)
then it wouldn't compile, because it's of type Unit, not IntArray.
So traditionally, you'd have to do something like this:
val ret = IntArray(size)
ret.fill(-1)
return ret
apply enables you to avoid this, because the return type is still of type IntArray (or T, in general).
Take this one:
class X {
var a: Int? = null
var b: Int? = null
fun first(a: Int) = apply { this.a = a }
fun second(b: Int) = apply { this.b = b }
}
X().first(2).second(3)
The apply functions are used to return the instance of X after setting the property. This enables builder-style call of both methods. If apply were removed, the function would return Unit.

How can I test that the return value from a function in go is a pointer to a type?

I have highlighted in the test case where I expect something should go. Ideally I would like to test that i is an instance of WHAT_SHOULD_I_PUT_HERE
main.go
package main
import "fmt"
type SomeType struct {
thingThatNeedsSetup struct{}
}
func Create() *SomeType {
return &SomeType{}
}
func main() {
a := Create()
fmt.Println(a.thingThatNeedsSetup)
}
main_test.go
package main
import (
"testing"
)
func TestCreate(t *testing.T) {
i := Create()
if i != WHAT_SHOULD_I_PUT_HERE {
t.Error()
}
}
Go is a typed language and so the go compiler guarantees that a function defined as such
func Create() *SomeType
will always return a value of type *SomeType and because of that your example seems rather pointless.
If on the other hand you define the function as returning an interface, empty or not, e.g.
func Create() interface{}
the underlying type of the returned value could be anything that implements that interface, in which case testing for the underlying type may make sense in some cases.
You can use the reflect package to test whether two values have equal types. Specifically the function reflect.TypeOf which returns a value of type reflect.Type.
From the docs:
Type values are comparable, such as with the == operator. Two Type
values are equal if they represent identical types.
Example:
package main
import (
"testing"
"reflect"
)
func TestCreate(t *testing.T) {
i := Create()
if reflect.TypeOf(i) != reflect.TypeOf(&SomeType{}) {
t.Error()
}
}
rv := reflect.ValueOf(v)
rv.Kind() == reflect.Ptr

how to deal with embedded interfaces and share data between them

I would like to better understand how to use interfaces, mainly to split code in reusable components and at the same time make it more easy for testing, currently my main question is how to share/get data between the interfaces that belong to a main interface, for example:
https://play.golang.org/p/67CQor1_pY
package main
import (
"fmt"
)
type MainInterface interface {
SubInterfaceA
SubInterfaceB
}
type SubInterfaceA interface {
MethodA()
GetterA(s implementMain)
}
type SubInterfaceB interface {
MethodB()
GetterB(s implementMain)
}
type implementA struct{}
func (ia *implementA) MethodA() { fmt.Println("I am method A") }
func (ia *implementA) GetterA(s implementMain) {
fmt.Println(s.Data)
}
type implementB struct{}
func (ib *implementB) MethodB() { fmt.Println("I am method B") }
func (ib *implementB) GetterB(s implementMain) {
fmt.Println(s.Data)
}
type implementMain struct {
Data string
SubInterfaceA
SubInterfaceB
}
func New(d string) implementMain {
return implementMain{
Data: d,
SubInterfaceA: &implementA{},
SubInterfaceB: &implementB{},
}
}
func main() {
var m MainInterface
m = New("something")
fmt.Println(m.(implementMain).Data)
m.MethodA() // prints I am method A
m.MethodB() // prints I am method B
m.GetterA(m.(implementMain)) // prints "something"
m.GetterB(m.(implementMain)) // prints "something"
}
In the above code, within the methods of struct implementA or implementB how to access the struct elements of the parent holder implementMain that implements MainInterface without passing it as an argument?
with holder struct I mean:
type implementMain struct {
Data string
SubInterfaceA
SubInterfaceB
}
If I am right SubInterfaceA and SubInterfaceB are embedded and help to make the struct implementMain satisfy the MainInterface:
type MainInterface interface {
SubInterfaceA
SubInterfaceB
}
But within the embedded methods of the SubInterfaceA or subInterfaceB what is the best practice to use in order to be available to get the data string?
I created Getter(s implementMain) method and passed the holder struct, but had to cast type:
m.GetterA(m.(implementMain))
I don't know if by satisfying a interface, all the involved interfaces can become part of the same structure scope and if they do, how to get/share data between them or either between its components?, for example besides been available to reach data string how from SubInterfaceA get/access SubInterfaceB

is it possible to call overridden method from parent struct in Golang?

I want to implement such code, where B inherit from A and only override A's Foo() method, and I hope the code to print B.Foo(), but it still print A.Foo(), it seems that the receiver in Golang can't work like this in C++, in which when dynamic binding is enabled, the code can work like what I want.
I also post another piece of code, which works, but it's too hard to implement, and more like a hack way, I think it's not a Golang style.
So my problem is: if the parent's Bar() method has some logic, for example, open a file, then read some lines, and use Foo() to output these lines to stdout, and the Child (in the example is B) wants to use most of them, the only difference is that the Child wants Foo() to output the lines to another file. How should I implement it? I have heard that Golang's inheritance can't work like C++ or Java, and what's right way in Golang?
package main
import (
"fmt"
)
type A struct {
}
func (a *A) Foo() {
fmt.Println("A.Foo()")
}
func (a *A) Bar() {
a.Foo()
}
type B struct {
A
}
func (b *B) Foo() {
fmt.Println("B.Foo()")
}
func main() {
b := B{A: A{}}
b.Bar()
}
output: A.Foo()
the following piece works, but when write
a := A{}
a.Bar()
you will encounter a compiler error
package main
import (
"fmt"
)
type I interface {
Foo()
}
type A struct {
i I
}
func (a *A) Foo() {
fmt.Println("A.Foo()")
}
func (a *A) Bar() {
a.i.Foo()
}
type B struct {
A
}
func (b *B) Foo() {
fmt.Println("B.Foo()")
}
func main() {
b := B{A: A{}}
b.i = &b // here i works like an attribute of b
b.Bar()
output: B.Foo()
As you wrote, what Go has is not really inheritance, the method that allows inheritance like features is called Embedding.
http://golang.org/doc/effective_go.html#embedding
What it means basically is that the embedded struct has no idea that it is embedded, so you cannot override anything that is called from it. You can actually take the embedded struct and take a reference for it only from the embedding struct.
So your best way to do it is more or less like your second example - through some sort of dependency injection using interfaces. i.e - A has a reference to some interface that does the actual work, say worker, that writes to a file or whatever. Then when instantiating B, you also replace A's worker with another worker (you can do it even without embedding A of course). The A just does something like myWorker.Work() without caring what worker it is.
Been struggling with this myself. Found 2 solutions:
Idiomatic Go way: implement the common "method" as external function with interface as argument.
package main
import "fmt"
// Fooer has to Foo
type Fooer interface {
Foo()
}
// Bar is a proxy, that calls Foo of specific instance.
func Bar(a Fooer) {
a.Foo()
}
//////////////////////////////////////////////////////////////////////
// usage
func main() {
b := &B{} // note it is a pointer
// also there's no need to specify values for default-initialized fields.
Bar(b) // prints: B.Foo()
}
//////////////////////////////////////////////////////////////////////
// implementation
// A is a "base class"
type A struct {
}
func (a *A) Foo() {
fmt.Println("A.Foo()")
}
// B overrides methods of A
type B struct {
A
}
func (b *B) Foo() {
fmt.Println("B.Foo()")
}
Try it on Go Playground: https://play.golang.org/p/2TbmHUs9_Dt
Similar to your second option: interface hackery. However, since Bar() is not specific to A (it is common to A and B), let's move it to base class, and hide implementation details and all dangerous stuff:
package main
import "fmt"
//////////////////////////////////////////////////////////////////////
// Usage
func main() {
b := NewB()
b.Bar() // prints: B.Foo()
a := NewA()
a.Bar() // prints: A.Foo()
}
//////////////////////////////////////////////////////////////////////
// Implementation.
// aBase is common "ancestor" for A and B.
type aBase struct {
ABCD // embed the interface. As it is just a pointer, it has to be initialized!
}
// Bar is common to A and B.
func (a *aBase) Bar() {
a.Foo() // aBase has no method Foo defined, so it calls Foo method of embedded interface.
}
// a class, not exported
type a struct {
aBase
}
func (a *a) Foo() {
fmt.Println("A.Foo()")
}
// b class, not exported
type b struct {
aBase
}
func (b *b) Foo() {
fmt.Println("B.Foo()")
}
//////////////////////////////////////////////////////////////////////
// Now, public functions and methods.
// ABCD describes all exported methods of A and B.
type ABCD interface {
Foo()
Bar()
}
// NewA returns new struct a
func NewA() ABCD {
a := &a{}
a.ABCD = a
return a
}
// NewB returns new struct b
func NewB() ABCD {
b := &b{}
b.ABCD = b
return b
}
Try it on Go Playground: https://play.golang.org/p/0Zcs_arturP
Recently I have a need to do this and the composition method proposed by OP works great.
I try to create another example to try to demonstrate the parent and child relationship and make it easier to read.
https://play.golang.org/p/9EmWhpyjHf:
package main
import (
"fmt"
"log"
)
type FruitType interface {
Wash() FruitType
Eat() string
}
type Fruit struct {
name string
dirty bool
fruit FruitType
}
func (f *Fruit) Wash() FruitType {
f.dirty = false
if f.fruit != nil {
return f.fruit
}
return f
}
func (f *Fruit) Eat() string {
if f.dirty {
return fmt.Sprintf("The %s is dirty, wash it first!", f.name)
}
return fmt.Sprintf("%s is so delicious!", f.name)
}
type Orange struct {
*Fruit
}
func NewOrange() *Orange {
ft := &Orange{&Fruit{"Orange", true, nil}}
ft.fruit = ft
return ft
}
func NewApple() *Fruit {
ft := &Fruit{"apple", true, nil}
return ft
}
func (o *Orange) Eat() string {
return "The orange is so sour!"
}
func main() {
log.Println(NewApple().Eat())
log.Println(NewApple().Wash().Eat())
log.Println(NewOrange().Eat())
log.Println(NewOrange().Wash().Eat())
}
Go does not support virtual method overriding. The design pattern you want to use is thus not directly supported by Go. It is considered bad practice because changing the implementation of A.Bar() would break all derived classes like B that assume A.Foo() will be called by A.Bar(). The design pattern you want to use will make your code brittle.
The way to do it in Go would be to define a Fooer interface with a Foo() method. A Fooer would be passed as argument to Bar() or stored in a field of A and called by A.Bar(). To change the Foo action, change the Fooer value. This is called composition, and it is much better than changing Foo action by inheritance and method overriding.
Here is an idiomatic way to do what you want to do in Go: https://play.golang.org/p/jJqXqmNUEHn. In this implementation, the Fooer is a member field of A that is initialized by a parameter of to the instance factory function NewA(). This design pattern is preferable when the Fooer doesn't change frequently during the lifetime of A. Otherwise, you may pass the Fooer as parameter of the Bar() method.
This is how we change the behavior of Foo() in Go. It is called composition because you change the behavior of Bar() by changing the instances composing A.
package main
import (
"fmt"
)
type Fooer interface {
Foo()
}
type A struct {
f Fooer
}
func (a *A) Bar() {
a.f.Foo()
}
func NewA(f Fooer) *A {
return &A{f: f}
}
type B struct {
}
func (b *B) Foo() {
fmt.Println("B.Foo()")
}
type C struct {
}
func (c *C) Foo() {
fmt.Println("C.Foo()")
}
func main() {
a := NewA(new(B))
a.Bar()
a.f = &C{}
a.Bar()
}
PS: Here is a possible implementation of the design pattern you wanted to implement for documentation purpose: https://play.golang.org/p/HugjIbYbout
package main
import (
"fmt"
)
//-- polymorphism in work
// children specification by methods signatures
// you should define overridable methods here
type AChildInterface interface {
Foo()
}
type A struct {
child AChildInterface
}
//-- /polymorphism in work
// hard A.Bar method
func (a *A) Bar() {
a.child.Foo() // Foo() will be overwritten = implemented in a specified child
}
//-- default implementations of changeable methods
type ADefaults struct{}
func (ad ADefaults) Foo() {
fmt.Println("A.Foo()")
}
//-- /default
//-- specified child
type B struct {
ADefaults // implement default A methods from ADefaults, not necessary in this example
}
// overwrite specified method
func (b B) Foo() {
fmt.Println("B.Foo()")
}
//-- /specified child
func main() {
a := A{ADefaults{}}
a.Bar()
// Golang-style inheritance = embedding child
b := A{B{}} // note: we created __Parent__ with specified __Child__ to change behavior
b.Bar()
}
Output:
A.Foo()
B.Foo()
Coming from C++/Python, where OOP is much better represented, and discovering go (now everything is web or web related, right?!) I too stumbled upon this issue. I feel that OOP in go is only half-baked. With embedding (struct's anonymous fields), methods of the inner type come along for free, inducing the idea of inheritance, only to learn later on the limitations. However, playing a bit with embedded interfaces within structs and with a bit of discipline, C++-like constructors, inheritance, polymorphism, and methods override can be emulated.
Considering the example - https://play.golang.org/p/nqt0haPYt2x
package main
import (
"bytes"
"fmt"
"log"
"math"
"unsafe"
)
//Emulate C++ like polymorphism in go, through template method design pattern
//========================== Shape interface ==============================
//like C++ abstract classes
type Shape interface {
Area() float32 //Shape's area
Perimeter() float32 //Shape's perimeter
Name() string //Shape's name (like rectangle, circle, square etc.)
}
//====================== PrintableShapeInfo =============================
type PrintableShapeInfo struct {
Shape //like C++ inheritance, although go has no such a thing
preetyPrintPrefix string
}
//Init a new PrintableShapeInfo object. The method is distinct so that it can be called from other contexts as well
//
//Remark: emulates the C++ constructor init part
func (printableShapeInfo *PrintableShapeInfo) Init(preetyPrintPrefix string) {
printableShapeInfo.preetyPrintPrefix = preetyPrintPrefix
}
//The central method emulates the template method design pattern. It prints some info about a shape by dynamically calling (through pointers) the right methods
//
//Remark: the design patterns best practices recommend to favor composition over inheritance (i.e. model a ShapeInfoPrinter class, which takes a Shape interface and prints its info),
//for the sake of showcasting the template method pattern, the "go's inheritange" like model was chosen
func (printableShapeInfo *PrintableShapeInfo) PrintInfo() {
log.Println("PrintableShapeInfo::PrintInfo")
fmt.Printf("%s PrintableShapeInfo::PrintInfo - %s:\n",
printableShapeInfo.preetyPrintPrefix, printableShapeInfo.Name()) //dynamically calls (through a pointer) a shape's Name method (like Rectangle.Name or Circle.Name or Square.Name)
fmt.Printf("\tArea: %f\n", printableShapeInfo.Area()) //dynamically calls (through a pointer) a shape's Area method (like Rectangle.Area or Circle.Area or Square.Area)
fmt.Printf("\tPerimeter: %f\n", printableShapeInfo.Perimeter()) //dynamically calls (through a pointer) a shape's Perimeter method (like Rectangle.Perimeter or Circle.Perimeter or Square.Perimeter)
}
//====================== Rectangle =============================
type Rectangle struct {
PrintableShapeInfo //like C++ inheritence, although go has no such a thing
width float32 //rectangle's width
height float32 //rectangle's heigh
}
//Creates and init a new rectangle object and properly set its Shape's interface methods set (similar to C++ class' vtable)
//
//Remark: emulates the C++ constructor
func NewRectangle(width float32, height float32) *Rectangle {
log.Println("NewRectangle")
rectangle := new(Rectangle) //allocate data
rectangle.Shape = rectangle //set the Shape's specific vtable with the Rectangle's methods. Critical for template method pattern
rectangle.Init(width, height) //init class
return rectangle
}
//Init a new rectangle object. The method is distinct so that it can be called from other contexts as well (such as a square Init method. See below)
//
//Remark: emulates the C++ constructor init part
func (rectangle *Rectangle) Init(width float32, height float32) {
log.Println("Rectangle::Init")
//call the base's PrintableShapeInfo struct Init method
rectangle.PrintableShapeInfo.Init("###")
rectangle.width = width
rectangle.height = height
}
//Compute the rectangle's area
func (rectangle *Rectangle) Area() float32 {
log.Println("Rectangle::Area")
return float32(rectangle.width * rectangle.height)
}
//Compute the rectangle's perimeter
func (rectangle *Rectangle) Perimeter() float32 {
log.Println("Rectangle::Perimeter")
return float32(2 * (rectangle.width + rectangle.height))
}
//Get the rectangle's object name
func (rectangle *Rectangle) Name() string {
log.Println("Rectangle::Name")
return "rectangle"
}
//====================== Circle =============================
type Circle struct {
PrintableShapeInfo //like C++ inheritence, although go has no such a thing
radius float32 //circle's radius
}
//Creates and init a new circle object and properly set its Shape's interface methods set (similar to C++ class' vtable)
//
//Remark: emulates the C++ constructor
func NewCircle(radius float32) *Circle {
log.Println("NewCircle")
circle := new(Circle) //allocate data
circle.Shape = circle //set the Shape's specific vtable with the Rectangle's methods. Critical for template method pattern
circle.Init(radius) //init class
return circle
}
//Init a new circle object. The method is distinct so that it can be called from other contexts as well if needed
//
//Remark: emulates the C++ constructor init part
func (circle *Circle) Init(radius float32) {
log.Println("Circle::Init")
//call the base's PrintableShapeInfo struct Init method
circle.PrintableShapeInfo.Init("ooo")
circle.radius = radius
}
//Compute the circle's area
func (circle *Circle) Area() float32 {
log.Println("Circle::Area")
return math.Pi * float32(circle.radius*circle.radius)
}
//Compute the circle's perimeter
func (circle *Circle) Perimeter() float32 {
log.Println("Circle::Perimeter")
return 2 * math.Pi * float32(circle.radius)
}
//Get the circle's object name
func (circle *Circle) Name() string {
log.Println("Circle::Name")
return "circle"
}
//====================== Rectangle =============================
//Implement Square in terms of Rectangle
type Square struct {
Rectangle //like C++ inheritance, although go has no such a thing
}
//Creates and init a new square object and properly set its Shape's interface methods set (similar to C++ class' vtable)
//
//Remark: emulates the C++ constructor init
func NewSquare(width float32) *Square {
log.Println("NewSquare")
square := new(Square) //allocate data
square.Shape = square //set the Shape's specific vtable with the Rectangle's methods. Critical for template method pattern
square.Init(width) //init class
return square
}
//Init a new square object. The method is distinct so that it can be called from other contexts as well if needed
//
//Remark: emulates the C++ constructor init part
func (square *Square) Init(width float32) {
log.Println("Square::Init")
//since the Rectangle field is anonymous it's nice that we can directly call its un-overwritten methods but we can still access it, as named Rectangle, along with its (even overwritten) methods
square.Rectangle.Init(width, width) //call Rectangle's init to initialize its members. Since Square is implemented in Rectangle's terms, there nothing else needed
}
//Compute the square's area
func (square *Square) Area() float32 {
log.Println("Square::Area")
//since the Rectangle field is anonymous it's nice that we can directly call it's un-overwritten methods but we can still access it, as named Rectangle, along with it's (even overwritten) methods
return square.Rectangle.Area()
}
//Compute the square's perimeter
func (square *Square) Perimeter() float32 {
log.Println("Square::Perimeter")
//since the Rectangle field is anonymous it's nice that we can directly call it's un-overwritten methods but we can still access it, as named Rectangle, along with it's (even overwritten) methods
return square.Rectangle.Perimeter()
}
//Get the square's object name
func (square *Square) Name() string {
log.Println("Square::Name")
return "square"
}
func main() {
//initialize log subsystem so that we can display them at the main's end
// bufWriter := bytes.NewBuffer()
logStringWriter := bytes.NewBufferString("")
log.SetOutput(logStringWriter)
rectangle := NewRectangle(2, 3) //create a Rectangle object
rectangle.PrintInfo() //should manifest polymorphism behavior by calling Rectangle's Area, Perimeter and Name methods
circle := NewCircle(2) //create a Circle object
circle.PrintInfo() //should manifest polymorphism behavior by calling Circle's Area, Perimeter and Name methods
square := NewSquare(3) //create a Square object
square.PrintInfo() //should manifest polymorphism behavior by calling Square's Area, Perimeter and Name methods
//print constructs sizes
fmt.Printf(`
Go constructs sizes:
Shape interface size as seen by Rectangle struct: %d
`, unsafe.Sizeof(rectangle.Shape))
fmt.Printf("\tRectangle struct size: %d", unsafe.Sizeof(rectangle))
fmt.Printf(`
Shape interface size as seen by Circle struct: %d
`, unsafe.Sizeof(circle.Shape))
fmt.Printf("\tCircle struct size: %d", unsafe.Sizeof(circle))
fmt.Printf(`
Shape interface size as seen by Square struct: %d
`, unsafe.Sizeof(square.Shape))
fmt.Printf("\tCircle struct size: %d", unsafe.Sizeof(square))
//print the logs
fmt.Println("\n\nDumping traces")
fmt.Print(logStringWriter)
return
}
The central method (template method) is PrintInfo which, called for any defined shape, works as expected, by calling the right Area, Perimeter, and Name methods. Ex. circle.PrintInfo() will call circle.Area, circle.Perimeter and circle.Name.
The constructor functions, NewRectangle, NewCircle, and NewSquare construct shape objects and they're split into three steps:
space allocation
methods set (C++ like vtable) init, needed for polymorphic behavior
struct members initialization, through Init methods
The struct member initialization is a distinct step for better code reuse. For example, Rectangle Init calls the base PrintableShapeInfo Init method while the Square Init method calls the base Rectangle Init (which calls PrintableShapeInfo Init, as said before).
Also, due to interfaces embedding, the object sizes increases only a bit, with a pair of pointers to the methods set and data area as can be seen in the example output.
I think the code looks pretty decent and the only concern being if specifically setting the Shape's interface method set (as the case of NewRectangle, NewCircle, and NewSquare functions) would trigger some side effects, as the code appears to work correctly?!