How do you convert a float32 pointer *float32
to a float64 pointer *float64
.
package main
import "fmt"
func main() {
var value *float32
v := float64(*value)
vp := &v
fmt.Println(vp)
}
The following code returns
runtime error: invalid memory address or nil pointer dereference
CodePudding user response:
One method is to write a function to safely convert the float32 pointer to a float64 pointer.
package main
import "fmt"
func main() {
var value *float32
v := float32ToFloat64(value)
fmt.Println(v)
val := float32(1.2)
p := float32ToFloat64(&val)
fmt.Println(*p)
}
func float32ToFloat64(value *float32) *float64 {
if value == nil {
return nil
}
v := float64(*value)
return &v
}
CodePudding user response:
The reason your code is failing is simply that you are trying to dereference a pointer that has not been initialised:
var value *float32
declares a pointer to a float32
, but does not initialise it, resulting in a nil
pointer.
v := float64(*value)
Then tries to dereference value
but as we just identified, value
is nil
- it doesn't point to anything so asking for what it points to is bound to result in an error.
However, your code is actually fine, as long as you have a *float32
that actually points to a float32
, which we can see if we add an actual float32
variable and initialise value
to point to that:
package main
import "fmt"
func main() {
var vv float32 = 3.14159
var value *float32 = &vv
v := float64(*value)
vp := &v
fmt.Println(vp)
}
Which will output the address of the float64
value.
However, be aware that a float64
is not just a float32
that takes up twice as many bytes. The precision and the internal representation are different, as can be seen with a further modification to the code:
func main() {
var vv float32 = 3.14159
var value *float32 = &vv
v := float64(*value)
fmt.Println(vv)
fmt.Println(v)
}
you should see output similar to:
3.14159
3.141590118408203
This is not a bug, this is the result of the different internal representation of a float64
vs float32
.
There is no way to guarantee the exact same value in these different types - each has characteristics that make some values literally impossible to represent, from which it follows that it is impossible to guarantee that float32(v) == float64(v)
for every v
.
This is also why you cannot simply type-cast the pointer:
vp := *float64(value)
This is illegal because a pointer to a float64
is pointing to something fundamentally different than a pointer to a float32
.
By contrast you can simply typecast a *int32
as a *int64
.