Things I Wish Someone Had Told Me About Go
openmymind.net
openmymind.net
It's not clear from the first example if the writer actually understands pointers. The example code passes a pointer to a function and then modifies the pointer, not what it's pointing to. It was no surprise to me that this wouldn't modify the original thing the pointer was referencing. If they wanted to modify the pointer itself then they should have passed a * * User not a *User.
Go does, indeed, have pass-by-reference (use a pointer) or pass-by-value (don't use a pointer).
func main() {
u := &User{Name: "Leto"}
Modify(&u)
}
func Modify(u **User) {
u = &User{Name: "Paul"}
}
With no luck.If you want to cause side effects in a function, you have to dereference something. (or call another evil function)
The only exception being dot operators, which implicitly dereference their left hand argument.
(&x).whatever() == x.whatever()
I wish go had used arrow notation now. Explicitly marking side effects is a good thing.For example if you pass a struct, you are passing it by value, but if you pass a pointer to that struct, you are also passing by the argument by value. Why? Because even though the pointer contains a reference to the struct as its value, the pointer itself (which is the same as any other integer datatype to the computer) is being passed by value.
If your not familiar with pointers and C and languages with reference values like C++/Java this distinction isn't going to mean much to you however.
http://msdn.microsoft.com/en-gb/library/14akc2c7(v=vs.71).as...
I would expect that refs are roughly equivalent to the following
http://play.golang.org/p/3cwx5Qofc8
Where the commented out code represents the .net equivalent. I would expect that the .net compiler simply rewrites your code for you to hide the slightly tricky messing about with pointers. So the .net ref looks like a bit of syntactic sugar over what you were trying to do in your post.
The simple solution to your first example is to simply write to the Name field of the struct being pointed too.
http://play.golang.org/p/D3t0Iv8oG4
If you want to do complex pointer meddling (and replace the entire struct) you need this syntax.
http://play.golang.org/p/tMwHC-k-bu
As a side note I have personally used pointers to interfaces for doing search tree reordering. You can really do a lot of useful pointer operations without pointer arithmetic.
(A link to a quadtree implementation which uses pointers to interfaces, on line 119) https://github.com/fmstephe/location_server/blob/master/quad...
func main() {
u := &User{Name: "Leto"}
println(u.Name)
Modify(u)
println(u.Name)
}
func Modify(u *User) {
*u = User{Name: "Paul"}
}In declaration the '' goes on the left though. In general Go's syntax inverts the declaration w.r.t C/C++:
a int vs int a
b *int vs int* b
type X int vs typedef int X
NOTE: you can do unsafe pointer arithmetic using the "unsafe" package.
You can convert any pointer to a unsafe.Pointer and then you can convert it to a uintptr.There are also library functions designed to work with that, for example atomic.AddUintptr that atomically adds an offset to a pointer.
Although not intended as general use, it can be useful in low level library code. Otherwise you can do pretty much everything using slices.
What are you trying to do, and how would you think it works in your examples? I assume you're trying to change the name of the object being pointed to, but you're just assigning a new value to a variable that is passed to a function. Therefore, when the function returns, that value is 'lost'. How could it ever change the value of a member of the object you're pointing to? I have never written a line of Go in my life, but with the knowledge that Go supports some form of pointers, it's quite easy to trace this back to how it would work in C or C++; it also wouldn't work there, either. Knowing what a pointer is is easy, it's just memorizing a definition - knowing how they work takes some experience.
func main() {
u := User{Name: "Leto"}
Modify(&u)
}
func Modify(u *User) {
// u = &User{Name: "Paul"}
// you could, but why?
u.Name = "Paul"
}
I mean, if you read your code for main, you're saying "Declare u to be a pointer to a new User. Then call modify with the address of u... aka, the address of the pointer that points to the actual User object"...This is pretty much basic pointer stuff, the same as you would do in C: runnable: http://codepad.org/TeUZi1Wp
RE: "Go is pass by reference": I don't see anyone claiming that. The top comment is trying to be nice by saying that you can emulate pass by reference by passing a pointer (but you're really just passing the pointer by value).
I mean, what do you think this Java code prints (objects are references, but passed by val):
Runnable: http://rextester.com/JBZCLG13581
You should also consider the good comment above displaying how you actually CAN do REAL swapping in Go: http://news.ycombinator.com/item?id=5357959 (try that in Java... heh)
When I started learning Go, I kept seeing people talk about pass by reference, so I assumed it really did pass by reference (despite being uncommon). I was surprised to find out that it does pass by value.
You're correct about the "ref" keyword in C#, when used for the arg and parameter, it causes the function or method to act on the same chuck of memory as the alias represented in the caller.
I don't know about you, but I understand pointers from C, and then learning assembly. Go's behavior isn't different from C here.
Also, elsewhere you are discussing pass by value/pass by reference. Technically, C/Go/Java are pass by value. Passing pointers and de-referencing it is how pass-by-ref is emulated. You will notice that the top comment has qualified pass-by-reference with "passing pointers". That is colloquial terminology.
Also some of the built-in types like channels and maps are reference types (so they are always passed by reference).
If they were passed by reference, then we would expect this playground snip to print "false": http://play.golang.org/p/r6naknvzng
When you pass a slice around are are really passing a small struct around by value (http://golang.org/pkg/reflect/#SliceHeader), and it is that struct that contains the pointer to the data.
Interface Pointers
Note that the author of a type that fulfills an interface and the consumer of a function that takes an interface both have full control over how much data is copied on a call to the function. You can control whether a type fulfills an interface, or whether a pointer to the type fulfills the interface. In Go, it is always easy to tell how much memory is being copied for any function call.
type Jumper interface {
Jump()
}
func MakeItJump(j Jumper) {
// this function doesn't know what's wrapped inside the Jumper interface
// and doesn't need to care
j.Jump()
}
type Foo struct {
data [10]int64 // array of 10 8 byte numbers = 80 bytes on a copy
}
func (f *Foo) Jump() {
// we define Jump on Foo to take a copy of a pointer to a Foo.
// this means that when we pass a *Foo into MakeItJump,
// just a single pointer value is copied into the interface, \
// not the whole array inside Foo
}
type Bar uint8
func (b Bar) Jump() {
// we define Jump on Bar as taking a copy of the value of Bar
// since we know it only needs to copy an 8 bit integer to do so
} template <class T> void doSomething(const T &expensiveCopy);
Versus: template <class T> void doSomething(T cheapCopy);
As usual, boost provides another crazy template hack to work around this issue:Other than that, though, everything has been pretty cut and dry. There really aren't many "gotchas" in Go.
This is pretty true, although I would not bother using tip if writing a small command line utility or learning Go, but for a large project this is good advice. Execution time and memory usage are greatly improved in tip, at the cost you might run into bug that has not been fixed yet.
Here is the burn down to Go 1.1's release, when it hits bottom it releases. http://swtch.com/~rsc/go11.html# Go 1.1 RC should be out in April I believe.
Also if you need to pick a Go tip build to use this is useful: http://build.golang.org/
Anyone have a link to such a list? Seems like it'd be fun.
Every move you play is certainly not the best. You just need to focus on making the smallest mistakes as possible.
When someone retweeted this[1], I thought it was about golang problems.
[1] https://twitter.com/gogameguru/status/309695255056351232
I'd always wondered about that too. Thanks for one less mystery in the world.
'I understand what a pointer is'. Questionable.