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)
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.