Let's say I have a struct with state, and a few member functions on that struct.
Let's say that the struct member returns an instance of its own type, and I call additional functions on that instance, and pass the result of calling some other member on the initial instance as an argument.
Is the order of invocation between the first invocation, and the argument invocation, guaranteed?
(This pattern comes up a lot when trying to build "builder" type objects that have some internal state, like an expression stack.)
package main
import (
"fmt"
)
type q struct {
val int
}
func (s *q) getVal() int {
return s.val
}
func (s *q) a() *q {
s.val += 1
return s
}
func (s *q) b(i int) int {
return i + s.val
}
func main() {
s := &q{}
// this currently prints 2
// but is that guaranteed?
fmt.Println(s.a().b(s.getVal()))
}
Specifically, is the relative invocation order of s.a() versus s.getVal() guaranteed?
Golang defines the "lexical left-to-right order," but only for an individual expression, and s.a().b() seems like it's technically a different expression than s.getVal().
The behavior it currently has is the behavior I'd want and expect, but I can't tell whether it's also a behavior I can rely on "forever."
The relevant portion of the spec is:
all function calls, method calls, and communication operations are evaluated in lexical left-to-right order.
and
At package level, initialization dependencies override the left-to-right rule for individual initialization expressions, but not for operands within each expression:
Related
This question already has answers here:
Pointers vs. values in parameters and return values
(5 answers)
When to use pointers [duplicate]
(1 answer)
Difference between returning a pointer and a value in initialization methods [duplicate]
(1 answer)
Why should constructor of Go return address?
(2 answers)
Why should I use a pointer ( performance)?
(3 answers)
Closed 1 year ago.
I am doing a tour of go language, and I have a question about pointers.
Example code (https://tour.golang.org/methods/19):
package main
import (
"fmt"
"time"
)
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run() error {
return &MyError{
time.Now(),
"it didn't work",
}
}
func main() {
if err := run(); err != nil {
fmt.Println(err)
}
}
In this case it is using *MyError and &MyError, but I try to remove the * and & and it works correctly. Why are they using pointers in this example? What is the difference with normal variables? When should I use pointers or not?
"When should I use pointers?" is a very large question without a simple answer. Pointers are a way of passing a reference to a value, rather than a value itself, around, allowing you to modify the original value or "see" modifications to that value. It also prevents copying, which can be a performance improvement in very limited circumstances (do not pass pointers around all the time because it might be a performance improvement). Finally, pointers also let you represent "nothingness", which each pointer being able to be nil. This is both a blessing and a curse as you must check if each pointer is nil before accessing it, though.
In your specific example, the reason why returning &MyError works is because your Error() function operates on a value of *MyError (a pointer to MyError), rather than on a value of MyError itself. This means that *MyError implements the Error interface and is thus assignable to the error type, and so it can be returned from any function that expects an error as a return value.
Returning MyError wouldn't work on its own because MyError is not a *MyError. Go does some helpful things when dealing with function receivers: It will let you call any method on a MyError or *MyError if the receiver is *MyError, but it will only let you call methods on a *MyError if the type is *MyError - That is, Go will not "create" a pointer for you out of thin air.
If you were to remove * from func (e* MyError), you would be telling Go that Error() works on any instance of a MyError, which means that both *MyError and MyError would fulfill that contract. That's why both of the following are valid when you don't use a pointer receiver:
func (e MyError) Error() string {}
var _ error = MyError{} // Valid
var _ error = &MyError {}
In this particular case, using pointers will not make a difference. Here's one way to look at it:
In Go, all variables are passed by value. That means:
type T struct {...}
func f(value T) {..}
f(t)
Above, t is passed as value. That means when f is called, the compiler creates a copy of t and passed that to f. Any modifications f makes to that copy will not affect the t used to call f.
If you use pointers:
func f(value *T) {...}
f(&t)
Above, the compiler will create a pointer pointing to t, and pass a copy of that to f. If f makes changes to value, those changes will be made on the instance of t used to call f. In other words:
type T struct {
x int
}
func f(value T) {
value.x=1
}
func main() {
t:=T{}
f(t)
fmt.Println(t.x)
}
This will print 0, because the modifications made by f is done on a copy of t.
func f(value *T) {
value.x=1
}
func main() {
t:=T{}
f(&t)
fmt.Println(t.x)
}
Above, it will print 1, because the call to f changes t.
Same idea applies to methods and receivers:
type T struct {
x int
}
func (t T) f() {
t.x=1
}
func main() {
t:=T{}
t.f()
fmt.Println(t.x)
}
Above program will print 0, because the method modifies a copy of t.
func (t *T) f() {
t.x=1
}
func main() {
t:=T{}
t.f()
fmt.Println(t.x)
}
Above program will print 1, because the receiver of the method is declared with a pointer, and calling t.f() is equivalent to f(&t).
So, use pointers when passing arguments or when declaring methods if you want to modify the object, or if copying the object would be too expensive.
This is only a small part of the story about pointer arguments.
Version of Go
go version go1.11 darwin/amd64
Code 1:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
//func GotU(t esc);
func (e esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(test)
fmt.Println(test.i)
}
Code 2:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
func (e esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(&test)
fmt.Println(test.i)
}
Code 3:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
func (e *esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(test)
fmt.Println(test.i)
}
The outputs:
code 1 output: 9
code 2 output: 9
code 3 cannot be compiled due to a type mismatch
Since only func (e esc)GotU() implemented, why should both pieces of code work and deliver the same result?
It's kind of confusing for me to pass a pointer of struct to that function (TestFunc) to get the same answer.
The last code snippet has implemented a method receiver of pointer type. This will consider the situation if you want to modify the value of receiver.
func (e *esc) GotU() {
e.i = 10
}
In above case Since you are passing pointer type receiver on a method which is implementing the interface.
type myintf interface {
GotU()
}
So you need to pass address of struct in TestFunc. This is the reason you are getting type mismatch error, because you are passing variable of esc type while your method requires variable of *esc.
func main() {
var test esc
test.i = 9
TestFunc(&test)
fmt.Println(test.i)
}
Working example on Go playground
In Golang there are two ways to pass a method receiver.
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value
For programmers unaccustomed to pointers, the distinction between
these two examples can be confusing, but the situation is actually
very simple. When defining a method on a type, the receiver (s in the
above examples) behaves exactly as if it were an argument to the
method. Whether to define the receiver as a value or as a pointer is
the same question, then, as whether a function argument should be a
value or a pointer. There are several considerations
First, and most important, does the method need to modify the receiver? If it does, the receiver must be a pointer. (Slices and maps act as references, so their story is a little more subtle, but for instance to change the length of a slice in a method the receiver must still be a pointer.) In the examples above, if pointerMethod modifies the fields of s, the caller will see those changes, but valueMethod is called with a copy of the caller's argument (that's the definition of passing a value), so changes it makes will be invisible to the caller.
The difference between the 1st and second version is, that you pass the struct directly in one version and the pointer to the struct in the other version. In this case these programs work the same, as the pointer also includes the all defined funcs on the struct.
But this does not work the other way around. You define the method GotU on the pointer receiver. The struct does not know about this func. If you would call
TestFunc(&test)
in the third program, it would compile but work differently than the other two: The output is: "10"
As the GotU is defined on the pointer receiver test is passed as reference and the modifications persist. In the other programs test is passed as value, i.e. it is copied, the copy is modified in GotU. When the func exits, the copy is discarded and the old version is still the same as before.
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
Let's say we have this kind of a struct (one of the simplest ever):
type some struct{
I uint32
}
And we want to have a variable of that type and to atomically increment in for loop (possibly in another goroutine but now the story is different). I do the following:
q := some{0}
for i := 0; i < 10; i++ {
atomic.AddUint32(&q.I,1) // increment [1]
fmt.Println(q.I)
}
We're getting what we'd expect, so far so good, but if we declare a function for that type as follows:
func (sm some) Add1(){
atomic.AddUint32(&sm.I,1)
}
and call this function in the above sample (line [1]) the value isn't incremented and we just get zeros. The question is obvious - why?
This has to be something basic but since I am new to go I don't realize it.
The Go Programming Language Specification
Calls
In a function call, the function value and arguments are evaluated in
the usual order. After they are evaluated, the parameters of the call
are passed by value to the function and the called function begins
execution. The return parameters of the function are passed by value
back to the calling function when the function returns.
The receiver sm some is passed by value to the method and the copy is discarded when you return from the method. Use a pointer receiver.
For example,
package main
import (
"fmt"
"sync/atomic"
)
type some struct {
I uint32
}
func (sm *some) Add1() {
atomic.AddUint32(&sm.I, 1)
}
func main() {
var s some
s.Add1()
fmt.Println(s)
}
Output:
{1}
Go Frequently Asked Questions (FAQ)
When are function parameters passed by value?
As in all languages in the C family, everything in Go is passed by
value. That is, a function always gets a copy of the thing being
passed, as if there were an assignment statement assigning the value
to the parameter. For instance, passing an int value to a function
makes a copy of the int, and passing a pointer value makes a copy of
the pointer, but not the data it points to.
Should I define methods on values or pointers?
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value
For programmers unaccustomed to pointers, the distinction between
these two examples can be confusing, but the situation is actually
very simple. When defining a method on a type, the receiver (s in the
above examples) behaves exactly as if it were an argument to the
method. Whether to define the receiver as a value or as a pointer is
the same question, then, as whether a function argument should be a
value or a pointer. There are several considerations.
First, and most important, does the method need to modify the
receiver? If it does, the receiver must be a pointer. (Slices and maps
act as references, so their story is a little more subtle, but for
instance to change the length of a slice in a method the receiver must
still be a pointer.) In the examples above, if pointerMethod modifies
the fields of s, the caller will see those changes, but valueMethod is
called with a copy of the caller's argument (that's the definition of
passing a value), so changes it makes will be invisible to the caller.
By the way, pointer receivers are identical to the situation in Java,
although in Java the pointers are hidden under the covers; it's Go's
value receivers that are unusual.
Second is the consideration of efficiency. If the receiver is large, a
big struct for instance, it will be much cheaper to use a pointer
receiver.
Next is consistency. If some of the methods of the type must have
pointer receivers, the rest should too, so the method set is
consistent regardless of how the type is used. See the section on
method sets for details.
For types such as basic types, slices, and small structs, a value
receiver is very cheap so unless the semantics of the method requires
a pointer, a value receiver is efficient and clear.
Your function need to receive a pointer for the value to be incremented, that way you are not passing a copy of the struct and on next iteration the I can be incremented.
package main
import (
"sync/atomic"
"fmt"
)
type some struct{
I uint32
}
func main() {
q := &some{0}
for i := 0; i < 10; i++ {
q.Add1()
fmt.Println(q.I)
}
}
func (sm *some) Add1(){
atomic.AddUint32(&sm.I,1)
}
The code below produces undesirable
[20010101 20010102].
When uncommenting the String func it produces better (but not my implementation):
[{20010101 1.5} {20010102 2.5}]
However that String func is never called.
I see that Date in DateValue is anonymous and therefore func (Date) String is being used by DateValue.
So my questions are:
1) Is this a language issue, a fmt.Println implementation issue, or
something else? Note: if I switch from:
func (*DateValue) String() string
to
func (DateValue) String() string
my function is at least called and panic ensues. So if I really want my method called I could do that, but assume DateValue is really a very large object which I only want to pass by reference.
2) What is a good strategy for mixing anonymous fields with
functionality like Stringer and json encoding that use reflection
under the covers? For example adding a String or MarshalJSON method
for a type that happens to be used as an anonymous field can cause
strange behavior (like you only print or encode part of the whole).
package main
import (
"fmt"
"time"
)
type Date int64
func (d Date) String() string {
t := time.Unix(int64(d),0).UTC()
return fmt.Sprintf("%04d%02d%02d", t.Year(), int(t.Month()), t.Day())
}
type DateValue struct {
Date
Value float64
}
type OrderedValues []DateValue
/*
// ADD THIS BACK and note that this is never called but both pieces of
// DateValue are printed, whereas, without this only the date is printed
func (dv *DateValue) String() string {
panic("Oops")
return fmt.Sprintf("DV(%s,%f)", dv.Date, dv.Value )
}
*/
func main() {
d1, d2 := Date(978307200),Date(978307200+24*60*60)
ov1 := OrderedValues{{ d1, 1.5 }, { d2, 2.5 }}
fmt.Println(ov1)
}
It's because you've passed in a slice of DateValues and not DateValue pointers. Since you've defined the String method for *DataValue, *DateValue is what fulfills the Stringer interface. This also prevents DateValue from fulfilling the Stringer interface via its anonymous Date member, because only one of either the value type (DateValue) or the pointer type (*DateValue) can be used to fulfill an interface. So, when fmt.Println is printing the contents of the slice, it sees that the elements are not Stringers, and uses the default struct formatting instead of the method you defined, giving [{20010101 1.5} {20010102 2.5}].
You can either make OrderedValues a []*DateValue or define func (dv DateValue) String() string instead of the pointer version.
Based on what #SteveM said, I distilled it to a simpler test case:
package main
import "fmt"
type Fooable interface {
Foo()
}
type A int
func (a A) Foo() { }
type B struct {
A
}
// Uncomment the following method and it will print false
//func (b *B) Foo() { }
func main() {
var x interface{} = B{}
_, ok := x.(Fooable)
fmt.Println(ok) // prints true
}
In other words, the Foo method is not part of the method set of B when the Foo method for *B is defined.
From reading the spec, I don't see a clear explanation of what is happening. The closest part seems to be in the section on selectors:
For a value x of type T or *T where T is not an interface type, x.f
denotes the field or method at the shallowest depth in T where there
is such an f.
The only way I can see this explaining what is going on is if when it is looking for a method Foo at shallowest depth in B, it takes into consideration the methods for *B too, for some reason (even though we are considering type B not *B); and the Foo in *B is indeed shallower than the Foo in A, so it takes that one as the candidate; and then it sees that that Foo doesn't work, since it's in *B and not B, so it gets rid of Foo altogether (even though there is a valid one inherited from A).
If this is indeed what is going on, then I agree with the OP in that this is very counter-intuitive that adding a method to *B would have the reverse consequence of removing a method from B.
Maybe someone more familiar with Go can clarify this.