Can I create an associative array of different objects in Go? - go

I want to set an instance of a some type as an element in an associative array. What type should I use?
var objects //???
//The constructor will return instance of the IndexController type
objects["IndexController"] = index.Constructor()
fmt.Println(objects)
I will be thankful!

Go maps are generally homogenous (each value is of the same type). If you want a different type per index, you can make an array of some interface that all of the objects in the array support. If you don't need the objects to support any methods at all, you can use the empty interface interface{}.
objects := make(map[string]interface{})
objects["IndexController"] = somethingThatReturnsAnIndexController()

Related

How to obtain the address of an object referenced by an interface

I have two interface objects which I would like to compare against each other. I don't only want to compare if their values are the same, I also want to know whether these two interfaces are referencing the same object or if they're referencing two different objects with equal values.
Is there some way to extract the address an interface references from an interface object? Then I could just compare the two addresses to know whether the two interfaces reference the same object.
If two interfaces have pointer values, then you can simply compare them:
func cmp(v1, v2 interface{}) bool {
return v1==v2
}
func main() {
a:=1
b:=1
c:=&a
cmp(&a,&b) // false
cmp(a, b) // true, compare values
cmp(c, &a) // true
}
Be careful here.
Two different interface values can never "reference" the "same object" as an interface value always contains a copy of the value you wrap in the interface value. Variable identity (your "same object") would be "equal address" which is undefined for values wrapped in an interface value as these wrapped values are not addressable. So a clear no to your question.
But of course you can store a pointer to your value in the interface value iff the pointer type satisfies the interface.
It is best avoided to talk about "object" and "reference". Go has values of certain types. Some values are addressable. You can store addresses of addressable values in appropriately typed pointer variables.

Append to the slice of base interface slice of the implementations

Why the below doesn't work?
locations := make([]*LocationEvent, 0)
data := make([]Event, 0)
data = append(data, locations...)
where *LocationEvent (struct) implements Event (interface).
While the below works fine:
data = append(data, &LocationEvent{}, &LocationEvent{})
So how it is different when expanding the actual []*LocationEvent slice using ...?
The slice type must match the type of the variadic arguments in the append function exactly. locations is of type []*LocationEvent, and thus not compatible with []Event. There is no automatic "downcasting" in Go when working with slices.
You have to copy the locations to a new slice of Event, or add the items of locations one-by-one to the data slice.
For more explanation look here: https://stackoverflow.com/a/12754757/6655315

Use map[string]SpecificType with method of map[string]SomeInterface into

I get cannot use map[string]MyType literal (type map[string]MyType) as type map[string]IterableWithID in argument to MapToList with the code below, how do I pass in a concrete map type to method that expects a interface type?
https://play.golang.org/p/G7VzMwrRRw
Go's interface convention doesn't quite work the same way as in, say, Java (and the designers apparently didn't like the idea of getters and setters very much :-/ ). So you've got two core problems:
A map[string]Foo is not the same as a map[string]Bar, even if Bar implements Foo, so you have to break it out a bit (use make() beforehand, then assign in a single assignment).
Interface methods are called by value with no pointers, so you really need to do foo = foo.Method(bar) in your callers or get really pointer-happy to implement something like this.
What you can do to more-or-less simulate what you want:
type IterableWithID interface {
SetID(id string) IterableWithID // use as foo = foo.SetID(bar)
}
func (t MyType) SetID(id string) IterableWithID {
t.ID = id
return t
}
...and to deal with the typing problem
t := make(map[string]IterableWithID)
t["foo"] = MyType{}
MapToList(t) // This is a map[string]IterableWithID, so compiler's happy.
...and finally...
value = value.SetID(key) // We set back the copy of the value we mutated
The final value= deals with the fact that the method gets a fresh copy of the value object, so the original would be untouched by your method (the change would simply vanish).
Updated code on the Go Playground
...but it's not particularly idiomatic Go--they really want you to just reference struct members rather than use Java-style mutators in interfaces (though TBH I'm not so keen on that little detail--mutators are supes handy to do validation).
You can't do what you want to do because the two map types are different. It doesn't matter that the element type of one is a type that implements the interface which is the element type of the other. The map type that you pass into the function has to be map[string]IterableWithID. You could create a map of that type, assign values of type MyType to the map, and pass that to the function.
See https://play.golang.org/p/NfsTlunHkW
Also, you probably don't want to be returning a pointer to a slice in MapToList. Just return the slice itself. A slice contains a reference to the underlying array.

this code uses the address of type?

the code at https://code.google.com/p/goauth2/source/browse/oauth/oauth.go#99 declares this type:
package oauth
...
type Config struct {...}
...
the suggested use of this is following:
var config = &oauth.Config{...}
I do not understand why this code takes the address of this type and why this is even possible in Go. I am a newbie. I thought that types are for the compiler, no? Please help.
The Go Programming Language Specification
Composite literals
Composite literals construct values for structs, arrays, slices, and
maps and create a new value each time they are evaluated. They consist
of the type of the value followed by a brace-bound list of composite
elements. An element may be a single expression or a key-value pair.
Given the declaration
type Point3D struct { x, y, z float64 }
one may write
origin := Point3D{} // zero value for Point3D
Taking the address of a composite literal generates a pointer to a
unique instance of the literal's value.
var pointer *Point3D = &Point3D{y: 1000}
It's an example of the use of a pointer to a composite literal.
This is taking the address of a new instance of the Config type, not the address of the type itself.

Golang, Go : mapping with returning interface?

http://golang.org/pkg/sort/
This is from Go example.
// OrderedBy returns a Sorter that sorts using the less functions, in order.
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter {
return &multiSorter{
changes: changes,
less: less,
}
}
What does this do by colon? Is it mapping? Is it closure? Too much new syntax here. What should I read to understand this syntax in Go?
It's a factory function, creating and initialising a struct of type multisorter:
https://sites.google.com/site/gopatterns/object-oriented/constructors
Additionally, Go "constructors" can be written succinctly using initializers within a factory function:
function NewMatrix(rows, cols, int) *matrix {
return &matrix{rows, cols, make([]float, rows*cols)}
}
Also, it is using named parameters when initialising:
http://www.golang-book.com/9
This allocates memory for all the fields, sets each of them to their zero value and returns a pointer. (Circle) More often we want to give each of the fields a value. We can do this in two ways. Like this:
c := Circle{x: 0, y: 0, r: 5}
The `less ...lessFunc` in the func declaration means:
any number of parameters, each of type `lessFunc` can be passed here, and will be stored in the slice `less`
So it creates a `multiSorter` struct, which supports the sort interface, and calling the sort method from that interface (and implemented by multiSorter) will cause the object to use each lessFunc in turn while sorting
Does this make sense? I can expand more if needed...

Resources