get the value from a pointer to a float32 from inside a struct? - go

I am pulling in some data from a db - and I have a pointer to a float32 - because if I use a pointer - then I am able to check if it is nil (which it quite often might be).
When it is not nil, I want to get the value - how do I dereference it so I can get the actual float32? I can't actually find a link for that anywhere! I know exactly what I want to do, and I just can't find the syntax in Go, which I am still very new to - all help appreciated.
I know how to dereference the pointer if it is a straight float32...
but if I have the following struct...
type MyAwesomeType struct{
Value *float32
}
Then after I do :
if myAwesomeType.Value == nil{
// Handle the error later, I don't care about this yet...
} else{
/* What do I do here? Normally if it were a straight float32
* pointer, you might just do &ptr or whatever, but I am so
* confused about how to get this out of my struct...
*/
}

The Go Programming Language Specification
Address operators
For an operand x of pointer type *T, the pointer indirection *x
denotes the variable of type T pointed to by x. If x is nil, an
attempt to evaluate *x will cause a run-time panic.
Use the * operator. For example,
package main
import "fmt"
type MyAwesomeType struct {
Value *float32
}
func main() {
pi := float32(3.14159)
myAwesomeType := MyAwesomeType{Value: &pi}
if myAwesomeType.Value == nil {
// Handle the error
} else {
value := *myAwesomeType.Value
fmt.Println(value)
}
}
Playground: https://play.golang.org/p/8URumKoVl_t
Output:
3.14159
Since you are new to Go, take A Tour of Go. The tour explains many things, including pointers.
Pointers
Go has pointers. A pointer holds the memory address of a value.
The type *T is a pointer to a T value. Its zero value is nil.
var p *int
The & operator generates a pointer to its operand.
i := 42
p = &i
The * operator denotes the pointer's underlying value.
fmt.Println(*p) // read i through the pointer p
*p = 21 // set i through the pointer p
This is known as "dereferencing" or "indirecting".
Unlike C, Go has no pointer arithmetic.

Related

Cannot use as type in assignment in go

when I compile my code, I get the following error message, not sure why it happens. Can someone help me point why? Thank you in advance.
cannot use px.InitializePaxosInstance(val) (type PaxosInstance) as
type *PaxosInstance in assignment
type Paxos struct {
instance map[int]*PaxosInstance
}
type PaxosInstance struct {
value interface{}
decided bool
}
func (px *Paxos) InitializePaxosInstance(val interface{}) PaxosInstance {
return PaxosInstance {decided:false, value: val}
}
func (px *Paxos) PartAProcess(seq int, val interface{}) error {
px.instance[seq] = px.InitializePaxosInstance(val)
return nil
}
Your map is expecting a pointer to a PaxosInstance (*PaxosInstance), but you are passing a struct value to it. Change your Initialize function to return a pointer.
func (px *Paxos) InitializePaxosInstance(val interface{}) *PaxosInstance {
return &PaxosInstance {decided:false, value: val}
}
Now it returns a pointer. You can take the pointer of a variable using & and, should you need the struct value itself, dereference it again with *.
After a line like
x := &PaxosInstance{}
or
p := PaxosInstance{}
x := &p
the value type of x is *PaxosInstance. And if you ever need to, you can dereference it back into a PaxosInstance struct value with
p = *x
You usually do not want to pass structs around as actual values, because Go is pass-by-value, which means it will copy the whole thing. Using struct values with maps and slices often results in logic errors because a copy is made should you iterate them or otherwise reference them except via index. It depends on your use-case, but your identifier Instance would infer that you would want to avoid duplications and such logic errors.
As for reading the compiler errors, you can see what it was telling you. The type PaxosInstance and type *PaxosInstance are not the same.
The instance field within the Paxos struct is a map of integer keys to pointers to PaxosInstance structs.
When you call:
px.instance[seq] = px.InitializePaxosInstance(val)
You're attempting to assign a concrete (not pointer) PaxosInstance struct into an element of px.instance, which are pointers.
You can alleviate this by returning a pointer to a PaxosInstance in InitializePaxosInstance, like so:
func (px *Paxos) InitializePaxosInstance(val interface{}) *PaxosInstance {
return &PaxosInstance{decided: false, value: val}
}
or you could modify the instance field within the Paxos struct to not be a map of pointers:
type Paxos struct {
instance map[int]PaxosInstance
}
Which option you choose is up to your use case.
For anyone else pulling their hair out: check your imports.
Not sure when it started happening, but my Visual Studio Code + gopls setup will occasionally insert an import line that references my vendored dependencies path instead of the original import path. I usually won't catch this until I start polishing code for release, or an error like this one pops up.
In my case this caused two otherwise identical types to not compare equally. Once I fixed my imports this resolved the error.

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 the pointer is losing its value in this Go program

I don't understand why the pointer s is nil even after the input() method initialised it. Any idea?
package main
import "fmt"
type ps string
func(s *ps)input(){
x := ps("a")
s = &x
}
func(s *ps)output(){
}
func main() {
var v *ps
v.input()
if v == nil{
fmt.Println("v shouldn't be nil")
}
}
Playground http://play.golang.org/p/jU2hoMP7TS
You need two things--main needs to allocate space for a ps that input can write into, which you can do by replacing var v *ps with v := new(ps). The string will be "", but it doesn't matter what it is, just that there's space set aside in memory for a string header that input can write to. As Momer said, otherwise the pointer's nil and your program panics trying to dereference it.
And in order to assign through a pointer, input needs to use *s = x. Since *s is, informally, "get what s points to", you can read that as "change what s points to to x". Usually the automatic ref/deref behavior around the dot operator and method calls saves you from that, but when you assign through a pointer type or do other operations (arithmetic, indexing, etc.) the dereference needs to be there in the code.
v value (0) is passed into v.input. Passed value is stored in a local variable s. s value is modified. No one is saving new s value back into v.
If you want something modified in your function, you must pass pointer to the value. (or reference for slices, maps and so on).
If you want to change pointer value, you should pass pointer to your pointer.
Alex

golang - Pointer idiosyncrasies

Need help understanding why this breaks. PrintFoo can be called using either pointer or value. Why not NumField?
http://play.golang.org/p/Kw16ReujRx
type A struct {
foo string
}
func (a *A) PrintFoo(){
fmt.Println("Foo value is " + a.foo)
}
func main() {
a := &A{foo: "afoo"}
(*a).PrintFoo() //Works - no problem
a.PrintFoo() //Works - no problem
reflect.TypeOf(*a).NumField() //Works - no problem - Type = main.A
reflect.TypeOf(a).NumField() //BREAKS! - Type = *main.A
}
From the documentation :
// NumField returns the number of fields in the struct v.
// It panics if v's Kind is not Struct.
func (v Value) NumField() int
You are calling it on a pointer, you have to call it on a struct instead, for example :
fmt.Println(reflect.Indirect(reflect.ValueOf(a)).NumField())
fmt.Println(reflect.Indirect(reflect.ValueOf(*a)).NumField())
When you're not sure if your value is a pointer or not, use reflect.Indirect:
Indirect returns the value that v points to. If v is a nil pointer,
Indirect returns a zero Value. If v is not a pointer, Indirect returns
v.
//edit:
NumField gets called on Value, not your actual object, for example of you do:
func main() {
a := &A{foo: "afoo"}
fmt.Printf("%#v\n", reflect.TypeOf(*a))
fmt.Printf("%#v\n", reflect.TypeOf(a))
}
You will get :
//*a
&reflect.rtype{size:0x8, ...... ptrToThis:(*reflect.rtype)(0xec320)}
//a
&reflect.rtype{size:0x4, ...... ptrToThis:(*reflect.rtype)(nil)}
As you can tell, it's a completely different beast.
The first one holds information about the pointer, hence ptrToThis points to the actual struct.
The second holds info about the struct itself.

Why do we need to use * to modify values of elementary datatypes but not of user defined structs?

I am new to Go and have some experience in C. Now the thing which confuses me the most is why, in the code below, we need to dereference str to modify value but not chk.j.
What additional thing is happening in here in the case of structs?
type test struct {
i int
j string
}
func main() {
str := new(string)
*str = "Need Astrik"
chk := new(test)
chk.i = 5
chk.j = "Confused"
fmt.Println("printing", chk.i, chk.j, *str)
}
See Selectors section in the spec:
Selectors automatically dereference pointers to structs. If x is a pointer to a struct,x.y is shorthand for (*x).y; if the field y is also a pointer to a struct, x.y.z is shorthand for (*(*x).y).z, and so on. If x contains an anonymous field of type *A, where A is also a struct type, x.f is shorthand for (*x.A).f.
In summary: pointer members of structs are dereferenced automatically.
For assignments there's no such shortcut, so assigning pointees is the same as in C:
*p = value
In the case of struct x with a member y that is a pointer you want to assign its target a value to:
*x.y = value
In case the x is a pointer to a struct, the expression above translates to
*((*x).y) = value
new creates a pointer. If you want to assign something to what the pointer is pointing to, you need to dereference it. If you didn't create your values with new, you wouldn't need to dereference any pointers:
//without magic := so you actually see the types of things
package main
import "fmt"
func main(){
var s string = "Hello World"
s = "hello"
var sp (*string) = &s
fmt.Println(s) //hello
fmt.Println(*sp) //hello
*sp = "world"
fmt.Println(s) //world
fmt.Println(*sp) //world
}
You don't need to dereference your test chk because . can behave like both -> and . from C depending on whether you use it on a struct or a pointer to a struct.

Resources