Changing a Type's Underlying Value via a Method in Golang - go

Can an instance of a go type change its underlying value? Thanks to a previous question I know I can make my function's receiver a pointer and change struct fields if my type is a struct.
However, I'm interesting in changing the underlying type's value. Consider a small program like this
type Foo string
func (f *Foo) ChangeMe() {
val := Foo("Hello World")
f = &val
//fmt.Println(*f)
}
func main() {
f := Foo("Nope")
f.ChangeMe()
fmt.Println(f)
}
My naive assumption was "OK, I've created a new Foo("Hello World") and then pointed f at it. Since receiver is a pointer (*Foo), this should change the value in main().
However, this does not work. The above program still prints out "Nope"
Interested both in what my incorrect assumption about go are, and any techniques for achieving what I want to do.

You're assigning a new pointer value to f instead of dereferencing it.
Dereference f and assign a new string value:
func (f *Foo) ChangeMe() {
*f = Foo("Hello World")
}

Related

I don't understand when to use pointers on go [duplicate]

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.

Given a method value, get receiver object

Is there a way in Go, to get the receiver object from a method value?
For example, is there any such MagicFunc that would make the following program output the string my info from the underlying Foo instance.
package main
import "fmt"
type Foo struct {
A string
}
func (foo *Foo) Bar() string {
return "bar"
}
func MyFunc(val interface{}) {
i := MagicFunc(val)
f := i.(Foo)
fmt.Println(f.A)
}
func main() {
f := Foo{A: "my info"}
MyFunc(f.Bar)
}
No, it is not possible to get the method's receiver instance.
The most you can get is the receiver's type if you use a method expression instead of method value but that won't help you get the my info string.
I wanted to deep-dive into this a bit and soon found this document: https://golang.org/s/go11func
As describe there, when MyFunc is entered val doesn't contain a reference to f.Bar but rather to a special function with the signature func() string. That function knows that it can retrieve the orignal f pointer by checking the well-known R0 register (in the example. On amd64 it appears to be dx, but that's an implementation detail obviously).
Thus there's no way to do this without using implementation specific assembly code, which would be very fragile.

Get method receiver with reflect [duplicate]

Is there a way in Go, to get the receiver object from a method value?
For example, is there any such MagicFunc that would make the following program output the string my info from the underlying Foo instance.
package main
import "fmt"
type Foo struct {
A string
}
func (foo *Foo) Bar() string {
return "bar"
}
func MyFunc(val interface{}) {
i := MagicFunc(val)
f := i.(Foo)
fmt.Println(f.A)
}
func main() {
f := Foo{A: "my info"}
MyFunc(f.Bar)
}
No, it is not possible to get the method's receiver instance.
The most you can get is the receiver's type if you use a method expression instead of method value but that won't help you get the my info string.
I wanted to deep-dive into this a bit and soon found this document: https://golang.org/s/go11func
As describe there, when MyFunc is entered val doesn't contain a reference to f.Bar but rather to a special function with the signature func() string. That function knows that it can retrieve the orignal f pointer by checking the well-known R0 register (in the example. On amd64 it appears to be dx, but that's an implementation detail obviously).
Thus there's no way to do this without using implementation specific assembly code, which would be very fragile.

What's happening with these pointers?

I wrote some odd code, but I'm not sure why it works and what I can learn from it. I have a slice type build from another struct. I made a function on the slice type to modify itself. To do this, I seem to have to throw around *'s a little much.
I'm trying to learn about pointers in Go and would like a little help. Here's an example (http://play.golang.org/p/roU3MEeT3q):
var ClientNames = []string {"Client A", "Client B", "ClientC"}
type InvoiceSummaries []InvoiceSummary
type InvoiceSummary struct {
Client string
Amt int
}
func (summaries *InvoiceSummaries) BuildFromAbove() {
for _, name := range ClientNames {
*summaries = append(*summaries, InvoiceSummary{name, 100})
}
}
My question is: What is the purpose for each of these * and why am I not using any &?
What is the purpose for each of these * ?
By making the method receiver as pointer, you could easily change the property of the object. I think that's one of the benefit. This example below will prove it.
package main
import "fmt"
type someStruct struct {
someVar int
}
func (s someStruct) changeVal1(newVal int) {
s.someVar = newVal
}
func (s *someStruct) changeVal2(newVal int) {
s.someVar = newVal
}
func main() {
s := someStruct{0}
fmt.Println(s) // {0}
s.changeVal1(3)
fmt.Println(s) // {0}
s.changeVal2(4)
fmt.Println(s) // {4}
(&s).changeVal2(5)
fmt.Println(s) // {5}
}
and why am I not using any &?
Pointer method receiver is quite special, it can also be called from non-pointer struct object. Both of s.changeVal2(4) and (&s).changeVal2(5) are valid & will affect the value of someVar.
Example http://play.golang.org/p/sxCnCD2D6d
You have to use a pointer for the receiver - (summaries *InvoiceSummaries) - because otherwise the argument is passed by value, having a pointer means you pass a reference to the value instead. If not for that, then you couldn't modify the collection at all.
Inside of the methods body you have use * because it is the dereferncing operator and returns the value at the address. Ampersand (&) is the opposite, it gives the address of a value.
Nothing wrong with your code but normally addresses to slices aren't used. A slice is a small struct that gophers are normally happy to pass by value. If a method or function is creating a new slice, the gopher is happy to return the new slice, by value again, as the return value.
Of course passing a slice by value doesn't guarantee anything about the backing store remaining unchanged when the method/function returns. So it can't be used as a way of guaranteeing the data elements of the slice haven't mutated.

Why isn't my Stringer interface method getting invoked? When using fmt.Println

Suppose I have the following code:
package main
import "fmt"
type Car struct{
year int
make string
}
func (c *Car)String() string{
return fmt.Sprintf("{make:%s, year:%d}", c.make, c.year)
}
func main() {
myCar := Car{year:1996, make:"Toyota"}
fmt.Println(myCar)
}
When I call fmt.Println(myCar) and the object in question is a pointer, my String() method gets called properly. If, however the object is a value, my output is formatted using the default formatting built into Go and my code to format the said object is not called.
The interesting thing is in either case if I call myCar.String() manually it works properly whether my object is either a pointer or value.
How can I get my object formatted the way I want no matter if the object is value-based or pointer-based when used with Println?
I don't want to use a value method for String because then that means every time it's invoked the object is copied which seams unreasonable. And I don't want to have to always manually called .String() either because I'm trying to let the duck-typing system do it's work.
When calling fmt.Println, myCar is implicitly converted to a value of type interface{} as you can see from the function signature. The code from the fmt package then does a type switch to figure out how to print this value, looking something like this:
switch v := v.(type) {
case string:
os.Stdout.WriteString(v)
case fmt.Stringer:
os.Stdout.WriteString(v.String())
// ...
}
However, the fmt.Stringer case fails because Car doesn't implement String (as it is defined on *Car). Calling String manually works because the compiler sees that String needs a *Car and thus automatically converts myCar.String() to (&myCar).String(). For anything regarding interfaces, you have to do it manually. So you either have to implement String on Car or always pass a pointer to fmt.Println:
fmt.Println(&myCar)
Methods
Pointers vs. Values
The rule about pointers vs. values for receivers is that value methods
can be invoked on pointers and values, but pointer methods can only be
invoked on pointers. This is because pointer methods can modify the
receiver; invoking them on a copy of the value would cause those
modifications to be discarded.
Therefore, for your String method to work when invoked on both pointers and values, use a value receiver. For example,
package main
import "fmt"
type Car struct {
year int
make string
}
func (c Car) String() string {
return fmt.Sprintf("{make:%s, year:%d}", c.make, c.year)
}
func main() {
myCar := Car{year: 1996, make: "Toyota"}
fmt.Println(myCar)
fmt.Println(&myCar)
}
Output:
{make:Toyota, year:1996}
{make:Toyota, year:1996}
Define your fmt.Stringer on a pointer receiver:
package main
import "fmt"
type Car struct {
year int
make string
}
func (c *Car) String() string {
return fmt.Sprintf("{maker:%s, produced:%d}", c.make, c.year)
}
func main() {
myCar := Car{year: 1996, make: "Toyota"}
myOtherCar := &Car{year: 2013, make: "Honda"}
fmt.Println(&myCar)
fmt.Println(myOtherCar)
}
Playground
Output:
{maker:Toyota, produced:1996}
{maker:Honda, produced:2013}
Then, always pass a pointer to instances of Car to fmt.Println. This way a potentially expensive value copy is avoided under your control.
The OP further asked:
OP: [when a value receiver is used] "Does this basically mean that if I have a large struct, then every time it goes through Println it will be copied?"
The following experiment is evidence that the answer is "yes" (when a value receiver is used). Note that the String() method increments the year in this experiment, and check how this affects the printed output.
type Car struct {
year int
make string
}
func (c Car) String() string {
s := fmt.Sprintf("{ptr:%p, make:%s, year:%d}", c, c.make, c.year)
// increment the year to prove: is c a copy or a reference?
c.year += 1
return s
}
func main() {
myCar := Car{year: 1996, make: "Toyota"}
fmt.Println(&myCar)
fmt.Println(&myCar)
fmt.Println(myCar)
fmt.Println(myCar)
}
With a value receiver (c Car), the following printed output shows that Go makes value copies of the Car struct, because the year increment is not reflected in subsequent calls to Println:
{ptr:%!p(main.Car={1996 Toyota}), make:Toyota, year:1996}
{ptr:%!p(main.Car={1996 Toyota}), make:Toyota, year:1996}
{ptr:%!p(main.Car={1996 Toyota}), make:Toyota, year:1996}
{ptr:%!p(main.Car={1996 Toyota}), make:Toyota, year:1996}
Changing the receiver to a pointer (c *Car) but changing nothing else, the printed output becomes:
{ptr:0xc420094020, make:Toyota, year:1996}
{ptr:0xc420094020, make:Toyota, year:1997}
{1998 Toyota}
{1998 Toyota}
Even when a pointer is provided as argument in a call to Println, i.e. fmt.Println(&myCar), Go still makes a value copy of the Car struct when a value receiver is used. The OP wants to avoid value copies being made, and my conclusion is that only pointer receivers satisfy that requirement.
It's only related to implementation of fmt instead of Go however.
String() with pointer receiver would be invoked by https://github.com/davecgh/go-spew since spew print things in this way:
v = reflect.ValueOf(arg)
...
switch iface := v.Interface().(type) {
case fmt.Stringer:
defer catchPanic(w, v)
if cs.ContinueOnMethod {
w.Write(openParenBytes)
w.Write([]byte(iface.String()))
w.Write(closeParenBytes)
w.Write(spaceBytes)
return false
}
w.Write([]byte(iface.String()))
return true
}
Generally speaking, it's best to avoid assigning values to variables via static initializers, i.e.
f := Foo{bar:1,baz:"2"}
This is because it can create exactly the complaint you're talking about, if you forget to pass foo as a pointer via &foo or you decide to use value receivers you end up making a lot of clones of your values.
Instead, try to assign pointers to static initializers by default, i.e.
f := &Foo{bar:1,baz:"2"}
This way f will always be a pointer and the only time you'll get a value copy is if you explicitly use value receivers.
(There are of course times when you want to store the value from a static initializer, but those should be edge cases)

Resources