Override a specific method of interface - go

I want to implement a slightly customized version of an Interface. Let's take sort.Interface as an example. We already have sort.IntSlice that implements the whole interface. But I want to implement an AbsoluteSort algorithm. For that, I only want to change the Less method. Something like this:
type AbsSortedArray struct {
sort.IntSlice
}
func (a AbsSortArray) Less(i, j int) bool {
return abs(a[i]) < abs(a[j]) // this causes an error as I don't have access to underlying array here
}
func abs(i int) int {
if i < 0 {
return i * -1
}
return i
}
So basically what I want to achieve is:
Inherit other methods like Len and Swap from the parent
Override Less method, BUT not with intent of stubbing/mocking, rather I want the access to the underlying object so that I can still implement my custom logic.

I don't have access to underlying array here
Actually, you do:
func (a AbsSortArray) Less(i, j int) bool {
return abs(a.IntSlice[i]) < abs(a.IntSlice[j])
}
But this AbsSortedArray is a cumbersome data type to use (as now you must deal with a struct with a slice member, rather than using a slice directly). It would probably be much more readable and maintanable in this specific example to just provide your own from-scratch implementation.

Related

Immutable Struct in Golang

Is it possible to define an immutable struct in Golang? Once initialized then only read operation on struct's field, no modification of field values. If so, how to do that.
It is possible to make a struct read-only outside of its package by making its members non-exported and providing readers. For example:
package mypackage
type myReadOnly struct {
value int
}
func (s myReadOnly) Value() int {
return s.value
}
func NewMyReadonly(value int) myReadOnly{
return myReadOnly{value: value}
}
And usage:
myReadonly := mypackage.NewMyReadonly(3)
fmt.Println(myReadonly.Value()) // Prints 3
There is no way to mark fields/variables as read only in a generic way. The only thing you could do is marking fields/variable as unexported (first letter small) and provide public getters to prevent other packages editing variables.
There is no way to define immutable structures in Go: struct fields are mutable and the const keyword doesn't apply to them. Go makes it easy however to copy an entire struct with a simple assignment, so we may think that passing arguments by value is all that is needed to have immutability at the cost of copying.
However, and unsurprisingly, this does not copy values referenced by pointers. And the since built-in collections (map, slice and array) are references and are mutable, copying a struct that contains one of these just copies the pointer to the same underlying memory.
Example :
type S struct {
A string
B []string
}
func main() {
x := S{"x-A", []string{"x-B"}}
y := x // copy the struct
y.A = "y-A"
y.B[0] = "y-B"
fmt.Println(x, y)
// Outputs "{x-A [y-B]} {y-A [y-B]}" -- x was modified!
}
Note : So you have to be extremely careful about this, and not assume immutability if you pass a parameter by value.
There are some deepcopy libraries that attempt to solve this using (slow) reflection, but they fall short since private fields can't be accessed with reflection. So defensive copying to avoid race conditions will be difficult, requiring lots of boilerplate code. Go doesn't even have a Clone interface that would standardize this.
Credit : https://bluxte.net/
if you write a functional struct by golang, it must be an immutable struct, eg
you can write maybe struct definite
type Maybe[T any] struct {
v T
valid bool
}
func (m Maybe[T]) Just() T {
return m.v
}
func (m Maybe[T]) Nothing() bool {
return m.valid == false
}
func Just[T any](v T) Maybe[T] {
return Maybe[T]{
v: v,
valid: true,
}
}
func Nothing[T any]() Maybe[T] {
return Maybe[T]{
valid: false,
}
}
the maybe struct is a immutable struct

Golang sorting slice of interfaces

I wrote a CLI tool in Golang to wrap an API and I love how simple it was to put together. Now I want to incorporate another API with a different JSON structure to get similar values. I created an interface for the structs to implement, but I don't quite understand how the type casting works in Golang.
Here is an example I put together:
I have a common interface Vehicle that exposes some methods
type Vehicle interface {
Manufacturer() string
Model() string
Year() int
Color() string
String() string
}
I also want to sort all structs that implement this interface so I added a Vehicles type that implements the sort interface
type Vehicles []Vehicle
func (s Vehicles) Len() int {
return len(s)
}
func (s Vehicles) Less(i, j int) bool {
if s[i].Manufacturer() != s[j].Manufacturer() {
return s[i].Manufacturer() < s[j].Manufacturer()
} else {
if s[i].Model() != s[j].Model() {
return s[i].Model() < s[j].Model()
} else {
return s[i].Year() < s[j].Year()
}
}
}
func (s Vehicles) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
The issue is when I implement the Vehicle interface with a new struct Car and try to sort a slice of Cars I get this exception
tmp/sandbox022796256/main.go:107: cannot use vehicles (type []Car) as type sort.Interface in argument to sort.Sort:
[]Car does not implement sort.Interface (missing Len method)
Here is the full code: https://play.golang.org/p/KQb7mNXH01
Update:
#Andy Schweig provided a good answer to the problem I posed, but i should have been more explicit that I am unmarshalling JSON into a slice of Car structs so his solution doesn't work in this more explicit case
( Please see the updated link to my code )
The problem is that Car implements Vehicle, but []Car is not []Vehicle. One is a slice of objects and the other is a slice of interfaces.
What you need as Andy Scheweig said, you need GetVehicles to return Vehicles ([]Vehicle). You can do the conversion inside the GetVehicles and afterwards if you need the Cars you can do type assertion.
Made some changes to your code, and works as you need it now.
https://play.golang.org/p/fM8EhSfsCU
Extending on Andy's answer... If you're using Go 1.8 (or have the option to update for your project), you can use the newly-added sort.Slice function to do this with regular slices, like you'd get from unmarshalling JSON: https://golang.org/pkg/sort/#Slice
You can't use []Car where Vehicles (or []Vehicle) is expected, even though Car implements the Vehicle interface. (Even though the element types are compatible, the slice types are different types, and types must match exactly.)
Fortunately, it's easy to fix your code. You just have to change the first few lines of GetVehicles to this:
func GetVehicles() Vehicles {
return Vehicles{
Car{
CarManufacturer: "Chevrolet",
CarModel: "Corvette",
CarYear: 1965,
CarColor: "Red",
},
This works because Car can be used where Vehicle is expected, because Car implements the Vehicle interface.

Call method on any array of structs that have underlying field

Let's say I have a bunch of structs (around 10).
type A struct {
ID int64
... other A-specific fields
}
type B struct {
ID int64
... other B-specific fields
}
type C struct {
ID int64
... other C-specific fields
}
If I have an array of these structs at any given time (either []A, []B, or []C), how can I write a single function that pulls the IDs from the array of structs without writing 3 (or in my case, 10) separate functions like this:
type AList []A
type BList []B
type CList []C
func (list *AList) GetIDs() []int64 { ... }
func (list *BList) GetIDs() []int64 { ... }
func (list *CList) GetIDs() []int64 { ... }
With general method on the slice itself
You can make it a little simpler if you define a general interface to access the ID of the ith element of a slice:
type HasIDs interface {
GetID(i int) int64
}
And you provide implementation for these:
func (x AList) GetID(i int) int64 { return x[i].ID }
func (x BList) GetID(i int) int64 { return x[i].ID }
func (x CList) GetID(i int) int64 { return x[i].ID }
And then one GetID() function is enough:
func GetIDs(s HasIDs) (ids []int64) {
ids = make([]int64, reflect.ValueOf(s).Len())
for i := range ids {
ids[i] = s.GetID(i)
}
return
}
Note: the length of the slice may be a parameter to GetIDs(), or it may be part of the HasIDs interface. Both are more complex than the tiny reflection call to get the length of the slice, so bear with me on this.
Using it:
as := AList{A{1}, A{2}}
fmt.Println(GetIDs(as))
bs := BList{B{3}, B{4}}
fmt.Println(GetIDs(bs))
cs := []C{C{5}, C{6}}
fmt.Println(GetIDs(CList(cs)))
Output (try it on the Go Playground):
[1 2]
[3 4]
[5 6]
Note that we were able to use slices of type AList, BList etc, we did not need to use interface{} or []SomeIface. Also note that we could also use e.g. a []C, and when passing it to GetIDs(), we used a simple type conversion.
This is as simple as it can get. If you want to eliminate even the GetID() methods of the slices, then you really need to dig deeper into reflection (reflect package), and it will be slower. The presented solution above performs roughly the same as the "hard-coded" version.
With reflection completely
If you want it to be completely "generic", you may do it using reflection, and then you need absolutely no extra methods on anything.
Without checking for errors, here's the solution:
func GetIDs(s interface{}) (ids []int64) {
v := reflect.ValueOf(s)
ids = make([]int64, v.Len())
for i := range ids {
ids[i] = v.Index(i).FieldByName("ID").Int()
}
return
}
Testing and output is (almost) the same. Note that since here parameter type of GetIDs() is interface{}, you don't need to convert to CList to pass a value of type []C. Try it on the Go Playground.
With embedding and reflection
Getting a field by specifying its name as a string is quite fragile (think of rename / refactoring for example). We can improve maintainability, safety, and somewhat the reflection's performance if we "outsource" the ID field and an accessor method to a separate struct, which we'll embed, and we capture the accessor by an interface:
type IDWrapper struct {
ID int64
}
func (i IDWrapper) GetID() int64 { return i.ID }
type HasID interface {
GetID() int64
}
And the types all embed IDWrapper:
type A struct {
IDWrapper
}
type B struct {
IDWrapper
}
type C struct {
IDWrapper
}
By embedding, all the embedder types (A, B, C) will have the GetID() method promoted and thus they all automatically implement HasID. We can take advantage of this in the GetIDs() function:
func GetIDs(s interface{}) (ids []int64) {
v := reflect.ValueOf(s)
ids = make([]int64, v.Len())
for i := range ids {
ids[i] = v.Index(i).Interface().(HasID).GetID()
}
return
}
Testing it:
as := AList{A{IDWrapper{1}}, A{IDWrapper{2}}}
fmt.Println(GetIDs(as))
bs := BList{B{IDWrapper{3}}, B{IDWrapper{4}}}
fmt.Println(GetIDs(bs))
cs := []C{C{IDWrapper{5}}, C{IDWrapper{6}}}
fmt.Println(GetIDs(cs))
Output is the same. Try it on the Go Playground. Note that in this case the only method is IDWrapper.GetID(), no other methods needed to be defined.
As far as I know, there is no easy way.
You might be tempted to use embedding, but I'm not sure there's any way to make this particular task any easier. Embedding feels like subclassing but it doesn't give you the power of polymorphism.
Polymorphism in Go is limited to methods and interfaces, not fields, so you can't access a given field by name across multiple classes.
You could use reflection to find and access the field you are interested in by name (or tag), but there are performance penalties for that and it will make your code complex and hard to follow. Reflection is not really intended to be a substitute for Polymorphism or generics.
I think your best solution is to use the polymorphism that Go does give you, and create an interface:
type IDable interface {
GetId() int64
}
and make a GetId method for each of your classes. Full example.
Generic methods require the use of interfaces and reflection.

How to create a literal slice of an alias to a builtin type in Go

I have some golang code that manipulates slices of an interface type (Comparable). To test my code, I want to create some fake data and operate on it. However, I'm having trouble doing this in a way that is not incredibly tedious. The only thing I can think to do is create a new type for testing (in this case an alias of type int) that satisfies the Comparable interface, and then feed my tests literal slices of that type. I envision it looking something like the following:
type Comparable interface {
LT(Comparable) bool
AsFloat() float64
}
type testInt int
func (self testInt) LT(other Comparable) bool {
return float64(self) < other.AsFloat()
}
func (self testInt) AsFloat() float64 {
return float64(self)
}
func TestAFunction(t *testing.T) {
FunctionToTest([]Comparable{7, 4, 2, 1})
....
}
However, with this example, the compiler will complain that type int cannot be used as a Comparable. I understand why this is happening, but I'm not sure how to solve it. First, I don't know how to create a literal of type testInt. Second, I have to write a significant number of these functions. Working with literal ints is far more convenient for my purposes.
Is there a way to work with type aliases of builtin types such that the compiler can correctly infer the correct type of literals with a minimum of code?
Additionally, is there perhaps a better way to accomplish what I am trying to do, i.e., generate hard data that satisfies an interface for use in testing?
func NewWhatevers(a ...int) (r []Whatever) {
r = make([]Whatever, len(a))
for i, v := range a {
r[i] = Whatever(v)
}
return
}
...
myWhatevers := NewWhatevers(7, 4, 2, 1)
There are a number of ways to accomplish this. The problem, as you correctly state, is that the Go compiler cannot automatically convert int to Comparable (since doing so would require finding all possible equivalent types, and figuring out which of those equivalent types satisfy the Comparable interface, and then if there are more than one... you get the idea). Thus, you'll have to do one of two things:
Write an explicit type conversion:
FunctionToTest([]Comparable{ testInt(7), testInt(4), testInt(2), testInt(1) })
However, if you need a lot of literals, this could get really annoying. Thus, you could also:
Write a function to convert []int to []Comparable:
func intToComparable(i []int) []Comparable {
c := make([]Comparable, len(i))
for i, v := range i {
c[i] = testInt(v)
}
return c
}
and then you'd only have to do:
FunctionToTest(intToComparable([]int{ 7, 4, 2, 1 }))
Additionally, is there perhaps a better way to accomplish what I am trying to do, i.e., generate hard data that satisfies an interface for use in testing?
Maybe. The problem you encountered is that []Comparable and []testInt are fundamentally different and cannot be exchanged as the underlying representation in memory is different.
If your code is less about individual item which are Comparable but more about slices of items which can be compared than you could refactor your code to work on whole Slices.
Have a look at how package sort does this: It doesn't operate on a slice of comparables but on a "comparable slice".
// FloatOrder is a slice with comparable and float-convertible elements
type FloatOrder interface {
Less(i, j int) bool // Compare element i and j and return true first is less than the other
Float(i int) float64 // Return element i as a float64
}
type testInts []int
func (n testInts) Less(i, j int) bool {return n[i] < n[j]}
func (n testInts) Float(i int) float64 { return float64(n[i]) }
func FunctionTotest(fo FloatOrder) { ... }
func TestAFunction(t *testing.T) {
FunctionToTest(testInts{1,2,3,4})
....
}
(Completely untested, illustration-only code)

Enforcing type in "generic" code with empty interfaces

Sorry for the ambiguous title.
I'm reading this book http://algs4.cs.princeton.edu/home/ and I thought it would be good to implement the examples in Go as a learning exercise, however the book uses Java as its language to describe code in.
One of the first chapters discusses setting up some core datatypes/container style classes to re-use later on but I'm having trouble trying to hammer these into a Go setting, mainly because these datatypes seem to be enjoying the use of Java generics.
For example, I've written the following code
package bag
type T interface{}
type Bag []T
func (a *Bag) Add(t T) {
*a = append(*a, t)
}
func (a *Bag) IsEmpty() bool {
return len(*a) == 0
}
func (a *Bag) Size() int {
return len(*a)
}
This works in principle in the sense that I can add items to a Bag and check its size and everything. However this also means that the following code is legal
a := make(bag.Bag,0,0)
a.Add(1)
a.Add("Hello world!")
a.Add(5.6)
a.Add(time.Now())
I was just wondering if there was any way of enforcing the type so it conforms to a contract similar to
Bag<T> bagOfMyType = new Bag<T>()
e.g.
Bag<Integer> bagOfInts = new Bag<Integer>()
I know Go doesn't have generics and they're not really The Go Way, but I was just wondering if it is a possible to "enforce" anything at compile time (probably not)
Sorry for the long post
EDIT: OK so I've been looking into this a little further, I've pretty much given up with the generics side of things (I understand this is not on the roadmap for Go) so I'm thinking of doing something similar to Haskell typeclasses with interfaces, e.g.
type T interface{}
type Bag interface {
Add(t T)
IsEmpty() bool
Size() int
}
type IntSlice []int
func (i *IntSlice) Add(t T) {
*i = append(*i, t.(int)) // will throw runtime exception if user attempts to add anything other than int
}
func (i *IntSlice) IsEmpty() bool {
return len(*i) == 0
}
func (i *IntSlice) Size() int {
return len(*i)
}
The problem with this is the type enforcement is only enforced at runtime.
Anyone got any ideas how to improve on this?
I'm new to Go myself, so I'm curious if someone will have a better answer, but here's how I see it:
You want compile-time enforcement that when Add() is called on an IntSlice, its parameter is an int. Well, here's how you do that:
func (i *IntSlice) Add(t int) {
*i = append(*i, t)
}
Since there aren't generics, the Add() method is going to be different for every type of Bag, so the Bag interface, assuming you need it, becomes just:
type Bag interface {
IsEmpty() bool
Size() int
}
That makes sense to me, because you can't pass a Bag around and throw just anything in it. Knowing that something is a Bag isn't enough to know how to call Add() on it; you must know what type of Bag you're dealing with.
You could make the interface specific to the type, like IntBag, but since only one type is actually going to satisfy that interface, you might as well get rid of the interface and change the name of IntSlice to IntBag.
Basically that means giving up entirely on anything generic-like, and just creating a type with some methods that do what you want:
type IntBag []int
func (b *IntBag) Add(i int) {
*b = append(*b, i)
}
func (b IntBag) IsEmpty() bool {
return len(b) == 0
}
func (b IntBag) Size() int {
return len(b)
}
Update: Sometimes generics really would come in handy. It seems to me we're left choosing on a case-by-case basis what exactly is best for a given problem. With empty interfaces and reflection, you can get some generic-like behavior, but it tends to be ugly and you give up some compile-time type checking. Or you give up on generics and have some code-duplication. Or you just do it a totally different way.
I asked a question a few weeks ago about how I should use Go to handle problems that look to me like they need class hierarchies. The answer was basically that there is no general solution; it's all case-by-case. I think the same applies for generics: there are no generics in Go, and there's no general solution for translating generics-based solutions to Go.
There are many cases where you might use generics in another language but interfaces are perfectly adequate (or truly shine) in Go. Your example here is one where interfaces aren't really a proper replacement. See also: Go Vs. Generics.
I'm pretty well-versed with Go. Generics are a hotly-debated topic, and there is currently nothing analogous to Java generics or C++ templates. The convention at the moment is to implement a "generic" type with an empty interface and then wrap it with a specific type implementation that makes sure only elements of that type are used. Here's an example with container/list from the Go standard library.
http://play.golang.org/p/9w9H1EPHKR
package main
import (
"container/list"
"fmt"
)
type IntList struct {
innerList *list.List
}
func NewIntList() *IntList {
return &IntList{list.New()}
}
func (l *IntList) Add(i int) {
// this is the only way to add an element to the list,
// and the Add() method only takes ints, so only ints
// can be added
l.innerList.PushBack(i)
}
func (l *IntList) Last() int {
lastElem := l.innerList.Back()
// We can safely type-assert to an int, because Add()
// guarantees that we can't put a non-int into our list
return lastElem.Value.(int)
}
func main() {
l := NewIntList()
l.Add(5)
l.Add(4)
l.Add(3)
l.Add(2)
l.Add(1)
fmt.Println("Expecting 1; got:", l.Last())
}

Resources