Golang struct initialization - go

There is a simple struct like this:
type Event struct {
Id int
Name string
}
What is the difference between these two initialization methods?
e1 := Event{Id: 1, Name: "event 1"}
e2 := &Event{Id: 2, Name: "event 2"}
Any why would I use either of these initialization methods?

The first method
e1 := Event{Id: 1, Name: "event 1"}
is initializing the variable e1 as a value with type Event.
The second
e2 := &Event{Id: 1, Name: "event1"}
is initializing e2 as a pointer to a value of type Event As you stated in the comments, the set of methods defined on a value of a given type are a subset of the set of methods defined on a pointer to a value of that type. This means that if you have a method
func (e Event) GetName() string {
return e.Name
}
then both e1 and e2 can call this method, but if you had another method, say:
func (e *Event) ChangeName(s string) {
e.Name = s
}
Then e1 is not able to use the ChangeName method, while e2 is.
This (e1 is not able to use the ChangeName method, while e2 is) is not the case (although it may have been at the time of writing for this help), thanks to #DannyChen for bringing this up and #GilbertNwaiwu for testing and posting in the comments below.
(To address the striked out section above: The set of methods defined on a struct type consist of the methods defined for the type and pointers to the type.
Instead, Go now automatically dereferences the argument to a method, so that if a method receives a pointer, Go calls the method on a pointer to that struct, and if the method receives a value, Go calls the method on the value pointed to by that struct. At this point my attempt to update this answer may be missing something important in semantics so if someone would like to correct this or clarify feel free to add a comment pointing to a more comprehensive answer. Here is a bit from the go playground illustrating this issue: https://play.golang.org/p/JcD0izXZGz.
To some extent, this change in how pointers and values work as arguments to methods defined on function affects some areas of the discourse below but I will leave the rest unedited unless someone encourages me to update it as it seems to be more or less correct within the context of general semantics of languages that pass by value vs. pointer.)
As to the difference between pointers and values, this example is illustrative, as pointers are ordinarily used in Go to allow you to mutate the values a variable is pointing to (but there are many more reasons one might use pointers as well! Although for typical use, this is normally a solid assumption). Thus, if you defined ChangeName instead as:
func (e Event) ChangeName(s string) {
e.Name = s
}
This function would not be very useful if called on the value receiver, as values (not pointers) won't keep changes that are made to them if they're passed into a function. This has to do with an area of language design around how variables are assigned and passed: What's the difference between passing by reference vs. passing by value?
You can see this on this example in the Go Playground: https://play.golang.org/p/j7yxvu3Fe6

The type of e1 is Event the type of e2 is *Event. The initialization is actually the same (using composite literal syntax, also not sure if that jargon is Go or C# or both?) but with e2 you using the 'address of operator' & so it returns a pointer to that object rather than the instance itself.

Related

Two structs having same receiver function implementations, how to remove the duplications

I have two structs that are having same receiver function implementations:
type A struct {
name string
// other fields
}
type B struct {
name string
// other fields
}
type AA struct {
resource A
}
func (a *AA) Get() string {
// process something with a.resource.name
return a.resource.name
}
type BB struct {
resource B
}
func (b *BB) Get() string {
// process something with b.resource.name
return b.resource.name
}
type I interface {
Get() string
}
both structs AA and BB have Get function, in order to satisfy the interface I, this might be a dumb question, but I dont know how I can simplify them to remove the duplications of two Get functions, tried:
having a generic struct and embedded in A & B - cant do this due
to json serializations in the system I use.
embedded AA in BB and calling AA.Get - wont work since name is inside B instead of A
Combine AA and BB with both fields like resourceA and resourceB - this complicates the Get function, since then it needs to handle
create a non-receiver function and use it for both AA and BB - this can work but since there are quite some fields I need, not just name, so the function will end up with quite many parameters.
I cant stop feeling there should be an easier way, and also trying/googling a way to simplify it, but non of them seems to work, could someone point me some directions or hints?
much appreciated!
[UPDATE]
I'm trying to create a Kubernetes operator, which has some CRDs (Custom Resource Definitions), and since I create a generic controller that just take the CRDs and calling their functions (that's why I have interface), but I found I need to implement functions that are exactly the same, like GetName, GetObject, or some functions that manipulate the data and get back the results, and they're all the same across those CRD structs.
I've decided to just create a function that takes required parameters, and reuse the function across the structs, thanks for all the comments.
If you have other suggestions, please feel free to comment or suggest, thanks!

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.

Immutable value of type '[String]' only has mutating members named 'sort'

Reading Apple's Swift guide, more specifically the Closures chapter I've stumbled upon a problem. A String array is declared
var names = ["Cris", "Alex", "Ewa", "Barry", "Daniella"]
The purpose of this section is to pass an array of Strings (the one above) and with the function sort(_:) have the same array back but sorted using an auxiliary method by providing a closure. The closure is the method backwards
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
Then an array, reversed, is declared and applied the method sort to the original array, names:
var reversed = names.sort(backwards)
AFAIK reversed should be inferred as an array of Strings but when I check it is inferred as var reversed: <>. Now, reversed doesn't store anything and an error pops up:
Immutable value of type '[String]' only has mutating members named 'sort'
Later on in the chapter the closure is simplified a lot but I get the same error as now so I tried to fix it when the expression is simple enough but I have no clue on what to do.
I don't know if the book forgot something or is my mistake, help will be appreciated. Thank you in advance!

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

How exactly are interface variables implemented in Go?

In the below code snippet, I'd like to understand what exactly gets stored in iPerson when its contents are still uninitialized: just a value of 0-bytes? Or is it actually a pointer under the hood (and also initialized to 0-bytes of course)? In any case, what exactly happens at iPerson = person?
If iPerson = person makes a copy of person, what happens then when an object implementing IPerson but with a different size/memory footprint gets assigned to iPerson? I understand iPerson is a variable stored on the stack, so its size must be fixed. Does that mean that the heap is actually used under the hood, so iPerson is actually implemented as a pointer, but assignments still copy the object, as demonstrated by the above code?
Here's the code:
type Person struct{ name string }
type IPerson interface{}
func main() {
var person Person = Person{"John"}
var iPerson IPerson
fmt.Println(person) // => John
fmt.Println(iPerson) // => <nil> ...so looks like a pointer
iPerson = person // ...this seems to be making a copy
fmt.Println(iPerson) // => John
person.name = "Mike"
fmt.Println(person) // => Mike
fmt.Println(iPerson) // => John ...so looks like it wasn't a pointer,
// or at least something was definitely copied
}
(This question is the result of me having second thoughts on the precise factual correctness of my answer to why runtime error on io.WriterString?. So I decided to try to do some investigation to understand how is it exactly that interface variables and assignments to them work in Go.)
EDIT: after having received a few useful answers, I'm still puzzled with this:
iPerson = person
iPerson = &person
—both are legal. However, to me, this raises the question of why the compiler allows such weak typing to occur? One implication of the above is this:
iPerson = &person
var person2 = iPerson.(Person) # panic: interface conversion: interface is *main.Person, not main.Person
whereas changing the first line fixes it:
iPerson = person
var person2 = iPerson.(Person) # OK
...so it's not possible to determine statically whether iPerson holds a pointer or a value; and it seems that anything can assign either one to it at runtime with no errors raised. Why was such design decision made? What purpose does it serve? It definitely does not to fit within the "type safety" mindset.
You ask why both of
iPerson = person
iPerson = &person
are permitted. They are both permitted because both person and &person implement the IPerson interface. This is obvious, because IPerson is the empty interface--every value implements it.
It's true that you can't determine statically whether a value of IPerson holds a pointer or a value. So what? All you know about IPerson is that any object stored in a value of that type implements the list of methods in the interface. The assumption is that those methods are implemented correctly. Whether IPerson holds a value or a pointer is irrelevant to that.
For example, if the method is supposed to change something stored in the object, then that the method pretty much has to be a pointer method, in which case only a pointer value can be stored in the variable of interface type. But if none of the methods change something stored in the object, then they can all be value methods, and a non-pointer value can be stored in the variable.
So, looks like internally, the interface variable does hold a pointer to what was assigned to it. An excerpt from http://research.swtch.com/interfaces:
The second word in the interface value points at the actual data, in this case a copy of b. The assignment var s Stringer = b makes a copy of b rather than point at b for the same reason that var c uint64 = b makes a copy: if b later changes, s and c are supposed to have the original value, not the new one.
My question
[...] what happens then when an object implementing IPerson but with a different size/memory footprint gets assigned to iPerson?
...also gets answered in the article:
Values stored in interfaces might be arbitrarily large, but only one word is dedicated to holding the value in the interface structure, so the assignment allocates a chunk of memory on the heap and records the pointer in the one-word slot.
So yeah, a copy on the heap is made and a pointer to it assigned to the interface variable. But, apparently, to the programmer, the interface variable has the semantics of a value variable not a pointer variable.
(Thanks to Volker for providing the link; but also, the first part of his answer is factually plain wrong... So I don't know if I should downvote for the misleading information or upvote for the non-misleading and rather useful link (which also happens to contradict his own answer).)
When you execute the following line:
iPerson = person
You are storing a Person value in the interface variable. Since assignment to a struct performs a copy, yes your code is taking a copy. To retrieve the struct from inside the interface you'll need to take another copy:
p := iPerson.(Person)
so you'd rarely want to do this with mutable types. If you instead want to store a pointer to the struct in the interface variable, you need to do this explicitly:
iPerson = &person
As far as what goes on under the hood, you are right that interface variables allocate heap space to store values larger than a pointer, but this is usually not visible to the user.

Resources