But, without pointer arithmetics or, despite many claims, pass-by-reference, Go's "pointers" feels like a more flexible form of Java/Ruby/Python/Node/....
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).
Gos lack of pointer arithmetic is one of the design decisions that allows go to be memory safe (http://en.wikipedia.org/wiki/Memory_safe) . If you need need to be naughty with pointers you can use the "unsafe" package. But some environments like GAE or Go playground do not allow this.
Also some of the built-in types like channels and maps are reference types (so they are always passed by reference).
Everything in Go is passed by value, even the "reference types". Those types are called reference types because they hold a reference to some value in memory, exactly like a pointer.
You are correct, I was not being clear. They are not Go reference types are not reference types in the same way that they are in other languages.
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.
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.
Indeed. They are pointers. You just cannot do pointer arithmetic on them.
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.
Yes. Thank you! I completely admit that I'm wrong. Nevertheless, 1 thing to add. Maybe I'm being pedantic, or maybe I still don't get it, but even Go's FAQ says "everything in Go is passed by value". If you call what Go does pass by reference, what do you call what C#'s "ref" keyword does?
There's really no such thing as pass by reference in Go. It's all pass by value. However, the value may be a pointer to other data that doesn't get copied. This is how pointers, maps, slices, and interfaces work (if you're passing an interface to another function that also takes an interface that is. If you're passing a non-interface value into a function that takes an interface, the value gets copied when it is wrapped in the interface... again, that value might be just a pointer or other small thing, or if you don't structure the code right, it might be a whole lot of data.. but usually it's not, because we write code specifically not to copy much data).
Besides the few special built-in types that are passed by reference, everything else if passed by value. (Even "reference types" are actually structs that are passed by value (http://golang.org/pkg/reflect/#SliceHeader). And not reference types in the sense they are in other languages.
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.
Yeah, I wish they hadn't called them "Reference types" - I think it's confusing. They're just value types that happen to have a small value and a pointer to the bigger data.
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.
> I understand what a pointer is, but it's entirely possible that I still don't grok Go.
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.
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.
You're displaying some basic conceptual problems with pointers. A simple Go example:
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
I wanted (and miserably failed) to show that Go wasn't pass by reference (which a lot of people, including on HN, insist that it is, even though the docs and the behavior are quite clear). Of course the simplistic example doesn't make much sense, why not just reassign u.Name? My point is that you can't simply reassign u (as other have pointed out, you can by dereferencing a pointer to a pointer...which is still pass by value)
I have never seen Go described as pass-by-reference, especially when it doesn't have references to begin with (in the C++ sense of evaluating what it points to instead of the address itself).
I think you're still pretty fundamentally confused.
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):
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)
If you write that in C#, and declare the argument as "ref User u", it'll print "newName". Which is what I think pass by reference is. Java and Go (and C) are pass by value.
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.
Well, like I said, I've never seen anyone claim Go as pass-by-reference. That having been said, the spec refers to slices and maps as "reference types" but it doesn't mean they're pass by reference. They're still passed as a pointer, you just don't see it.
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.
The author is obviously new to Go, and that's fine.... here's a clarification of interfaces:
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
}
I didn't quite "get" the point of the pointer/copy option on interfaces, but this makes it crystal clear. This works around such a common problem in writing C++ templates (which is really the only equivalent polymorphism if you want to dispatch a function on a native type):
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:
I'm making some assumptions about the compiler optimization: If T is something like "int", then passing by reference can be more costly, because a value that was once stored in a register now needs a real memory address and must be deferenced to read.
The "interface as a pointer" thing really threw me for a loop as well. It was bothering me so much (not knowing what was actually going on), and Googling was helping so little, that I actually hopped on the Go IRC channel. The guys on there set me straight in, literally, minutes. There's a great community around Go right now.
Other than that, though, everything has been pretty cut and dry. There really aren't many "gotchas" in Go.
That pointer example is a little weird. A C/C++ pointer used that way wouldn't print "Leto" "Paul", either. All it would do is update the local variable to point to a new object, but the caller would still be pointing to the original. I think the poster meant to use a pointer to a pointer here (which would work as intended in both Go and C/C++).
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.
If you read the golang-dev google groups mailing list you will see lots of micro-benchmarks posted for specific commits. The best test is to install both stable and tip on your machine and compile your application with both. In one of my application there was a 9% improvement, in another it was 53%. When Go 1.1 is released I presume the computer benchmarks game will be updated, which might make comparison, at lease with other languages, easier.
Wow, this displays a severe misunderstanding of how pointers work in general. It's not like the syntax for it in Go is any different, this code would look very similar in anything that has real pointers (C, for example), certainly in regards to the notation and syntax for pointers and references and such.
For reference, I posted this in a subthread above: the same example in C demonstrating using a pointer and passing it or declaring an object and passing it's address: http://codepad.org/TeUZi1Wp
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).