0

I can use methods like Text() on a big.Int and it works fine, but if I return a big.Int then use "myfunc().Text()" throws an error, whereas if I return a *big.Int, I get no error. Why can I use Text() on a big.Int, *big.Int, and on a function that returns *big.Int but not on a function whose return value is big.Int?

https://play.golang.org/p/ovgeQDHFstP

Based on this and other behavior (such as how it prints), it seems like *big.Int is the type that is intended for use, is that correct?

Also, if I make and use a variable of type big.Int or *big.Int, it is passed by reference. That's fine. But if I wanted to pass one by value, how is that best done?

Should I make a new big.Int and set it to the original value using Set() and pass that? Or should I pass the original big.Int in, and copy its value to a new big.Int using Set() inside the function? Or is there some other, better way of doing it?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
user40176
  • 319
  • 2
  • 10
  • 4
    Always use *big.Int. Go can take the address of a variable automatically (under some conditions), see https://tour.golang.org/methods/6 ff for why you can call Text on a big.Int. Never talk and think about a pointer as being a "reference": It is not. big.Ints are not designed to be passed as values. – Volker Feb 05 '19 at 04:34
  • 3
    Related: https://stackoverflow.com/questions/33587227/golang-method-sets-pointer-vs-value-receiver. All methods are defined for the pointer type, so you should use pointers to avoid confusion. A counter example is time.Time, where all methods are defined in the value type, so you should not use pointers. // In Go [everything is passed by value](https://golang.org/ref/spec#Calls). – Peter Feb 05 '19 at 05:01

2 Answers2

0

The Text() method is defined for receiver type *big.Int, so obviously you can call it on variables of that type and on return values of functions returning *big.Int. You can also call it on variables of type big.Int, because Go automatically takes the address of a variable when you're trying to call its pointer methods, just to save you the trouble of typing an extra ampersand.

However you can't call it on return value of a function returning big.Int, because that value is not addressable. Here's what the spec says about addressability:

For an operand x of type T, the address operation &x generates a pointer of type *T to x. The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.

Your return value is none of those things, so you can't use the pointer method any more than you can write foo := &myFunc(). To work around this, you could save the return value on a variable to make it addressable. But most likely your function should return a pointer in the first place.

Also note that there are no references in Go. Everything is passed by value, and pointers are values just like any other.

jussius
  • 3,114
  • 15
  • 21
-1

https://golang.org/pkg/math/big/ the Text() method has a pointer receiver, which means that you can only call a.Text() if a is *big.Int.

*big.Int is a pointer to big.Int, see https://play.golang.org/p/dD70b0tPeGp for a fixed version of your code

Gal Ben-Haim
  • 17,433
  • 22
  • 78
  • 131