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
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.
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
}
Related
I am testing out generics in go 1.18 and took a look at this example.
I would like to recreate that example but instead be able to pass in a slice of int or slice of float instead, and in the function I'll just sum up everything in the slice.
This is when I ran into some issues just iterating the slice. This is what I tried:
package main
import "fmt"
// NumberSlice constraint
type NumberSlice interface {
[]int64 | []float64
}
func add[N NumberSlice](n N) {
// want: to range over n and print value of v
for _, v := range n {
fmt.Println(v)
}
}
func main() {
ints := []int64{1, 2}
add(ints)
}
I got the error:
cannot range over n (variable of type N constrained by NumberSlice) (N has no core type)
How do I accomplish this?
A core type, for an interface (including an interface constraint) is defined as follows:
An interface T has a core type if one of the following conditions is
satisfied:
There is a single type U which is the underlying type of all types in the type set of T
or the type set of T contains only channel types with identical element type E, and all directional channels have the same direction.
Your interface constraint has no core type, because it has two underlying types: []int64 and []float64.
Therefore you can't use it where a core type is required. Notably range and make.
You can change the interface to require the base types, and then specify the slice in the function signature:
// still no core type...
type Number interface {
int64 | float64
}
// ...but the argument will be instantiated with either int64 or float64
func add[N Number](n []N) {
for _, v := range n {
fmt.Println(v)
}
}
This also works, but it's way more verbose:
type NumberSlice[N int64 | float64] interface {
// one core type []N
~[]N
}
func add[S NumberSlice[N], N int64 | float64](n S) {
for _, v := range n {
fmt.Println(v)
}
}
Could something like this work for you?
package main
import "fmt"
type NumberOrFloat interface {
int64 | float64
}
func add[N NumberOrFloat](n []N) {
for _, v := range n {
fmt.Println(v)
}
}
func main() {
ints := []int64{1, 2}
add(ints)
}
The difference here is that you define type constraints on array elements (not on array types): []N
This question already has an answer here:
golang pointer in range doesn't work
(1 answer)
Closed 4 years ago.
For these two struct
type A struct {
Number *int
}
type B struct {
Number int
}
If I want to loop on slice of B and assign the value of B.Number to new A.Number
func main() {
aSlice := []A{}
bSlice := []B{B{1}, B{2}, B{3}}
for _, v := range bSlice {
a := A{}
a.Number = &v.Number
aSlice = append(aSlice, a)
}
}
I will found that all aSlice a.Number is the same value and same pointer.
for _, v := range aSlice {
fmt.Printf("aSlice Value %v Pointer %v\n", *v.Number,v.Number)
}
Will print
aSlice Value 3 Pointer 0x10414020
aSlice Value 3 Pointer 0x10414020
aSlice Value 3 Pointer 0x10414020
So does range only update the value of _,v in for loop and doesn't change the pointer ?
Full Code : https://play.golang.org/p/2wopH9HOjwj
It occurred because variable v is created at the beginning of the loop and doesn't change. So, every element in aSlice has a pointer to the same variable. You should write this:
for _, v := range bSlice {
a := A{}
v := v
a.Number = &v.Number
aSlice = append(aSlice, a)
}
Here you create at every iteration new variable with its own pointer.
As #Adrian stated This has nothing to do with memory. The A struct is actually contains a pointer to integer value.
type A struct {
Number *int
}
So when you are assigning the value from bSlice to A struct and then appending the A struct in aSlice which is of A struct type. It will append the values as it is supposed to do inside Golang.
But you are changing the value at address pointed by A struct. And initialed with a new value in each iteration which changes the value at that address.
a.Number = &v.Number // here a.Number points to the same address
Hence the aSlice contains the value of last updated integer which is 3. Since aSlice is a slice of A struct it contains the value inside A struct which is 3.
But if you do not create a pointer to int inside A struct
type A struct {
Number int
}
you will get the output as expected with different address now as.
package main
import (
"fmt"
)
type A struct {
Number int
}
type B struct {
Number int
}
func main() {
aSlice := []A{}
bSlice := []B{B{1}, B{2}, B{3}}
fmt.Println("----Assignment Loop----")
for _, v := range bSlice {
a := A{}
a.Number = v.Number
aSlice = append(aSlice, a)
fmt.Printf("bSlice Value %v Pointer %v\n", v.Number, &v.Number)
fmt.Printf(" a Value %v Pointer %v\n", a.Number, &a.Number)
}
fmt.Println("\n----After Assignment----")
fmt.Printf("%+v\n", aSlice)
for i, _ := range aSlice {
fmt.Println(aSlice[i].Number)
}
}
Working Code on Go playground
In Golang spec It is defined for composite Literals as :
Taking the address of a composite literal generates a pointer to a
unique variable initialized with the literal's value.
type Point3D struct { x, y, z float64 }
var pointer *Point3D = &Point3D{y: 1000}
I defined my Int type as int.
I want to convert a slice of Int to a slice of int, but got a compile error:
cannot convert c (type []Int) to type []int
How can I fix this?
package main
import (
"fmt"
)
type Int int
func main() {
var c = []Int{}
var x = []int( c )
fmt.Println(len(x))
}
Your Int type is not an alias of int, it's a new type with int being its underlying type. This type of conversion is not supported / allowed by the language spec. More specifically, converting a slice type to another where the element type is different is not allowed.
The safe way
If you only need an []int "view" of the []Int, the safe way to "convert" would be to create a copy of the []Int slice but with a type of []int, and use a for range loop and convert each individual element from Int to int type:
var c = []Int{1, 2}
x := make([]int, len(c))
for i, v := range c {
x[i] = int(v)
}
fmt.Println(x)
Output (try it on the Go Playground):
[1 2]
The unsafe way
There is also an "unsafe" way:
var c = []Int{1, 2}
var x []int = *(*[]int)(unsafe.Pointer(&c))
fmt.Println(x)
Output is the same. Try this one on the Go Playground.
What happens here is that the address of c (which is &c) is converted to unsafe.Pointer (all pointers can be converted to this), which then is converted to *[]int (unsafe.Pointer can be converted to any pointer type), and then this pointer is dereferenced which gives a value of type []int. In this case it is safe because the memory layout of []Int and []int is identical (because Int has int as its underlying type), but in general, use of package unsafe should be avoided whenever possible.
If Int would be a "true" alias
Note that if Int would be a "true" alias to int, the conversion would not even be needed:
var c = []Int{1, 2}
var x []int = c
fmt.Println(x)
Output is the same as above (try it on the Go Playground). The reason why this works is because writing []Int is identical to writing []int, they are the same type, so you don't even need a conversion here.
By using a slice type
Also note that if you would create a new type with []int as its underlying type, you could use type conversion:
type IntSlice = []int
func main() {
var c = IntSlice{1, 2}
var x []int = []int(c)
fmt.Println(x)
}
Output is again the same. Try this one on the Go Playground.
The problem is that you are not creating Int as an alias, doing
type Int int
Will create Int as a new type that can't interoperate with int.
The proper way to create Int as an alias is
type Int = int
With this change your program is ok.
Technically, type Int int does not define an alias, but a completely new type. Even though Int and int now have identical underlying types and can be converted to each other, that does not apply to slices. More about allowed conversions is in the spec.
Actually, a slice a simply points to an underlying array of the designated type (in this case the types are different, Int and int). So unless your underlying type is the same a conversion won't work. Just to illustrate this something like this would work though:
package main
import (
"fmt"
)
type Int int
type IntSl []int
func main() {
var c = IntSl{2, 3, 4}
var x []int
x = []int(c)
var a Int
var b int
a = 1
b = int(a)
fmt.Println(len(x), a, b, c)
}
Playground : https://play.golang.org/p/ROOX1XoXg1j
As #icza points out there's the unsafe way & of course you can always do the conversion looping over each of the elements which could be expensive.
I'm curious why Go does't implicitly convert []T to []interface{} when it will implicitly convert T to interface{}. Is there something non-trivial about this conversion that I'm missing?
Example:
func foo([]interface{}) { /* do something */ }
func main() {
var a []string = []string{"hello", "world"}
foo(a)
}
go build complains
cannot use a (type []string) as type []interface {} in function argument
And if I try to do it explicitly, same thing: b := []interface{}(a) complains
cannot convert a (type []string) to type []interface {}
So every time I need to do this conversion (which seems to come up a lot), I've been doing something like this:
b = make([]interface{}, len(a), len(a))
for i := range a {
b[i] = a[i]
}
Is there a better way to do this, or standard library functions to help with these conversions? It seems kind of silly to write 4 extra lines of code every time I want to call a function that can take a list of e.g. ints or strings.
In Go, there is a general rule that syntax should not hide complex/costly operations.
Converting a string to an interface{} is done in O(1) time. Converting a []string to an interface{} is also done in O(1) time since a slice is still one value. However, converting a []string to an []interface{} is O(n) time because each element of the slice must be converted to an interface{}.
The one exception to this rule is converting strings. When converting a string to and from a []byte or a []rune, Go does O(n) work even though conversions are "syntax".
There is no standard library function that will do this conversion for you. Your best option though is just to use the lines of code you gave in your question:
b := make([]interface{}, len(a))
for i := range a {
b[i] = a[i]
}
Otherwise, you could make one with reflect, but it would be slower than the three line option. Example with reflection:
func InterfaceSlice(slice interface{}) []interface{} {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
// Keep the distinction between nil and empty slice input
if s.IsNil() {
return nil
}
ret := make([]interface{}, s.Len())
for i:=0; i<s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret
}
The thing you are missing is that T and interface{} which holds a value of T have different representations in memory so can't be trivially converted.
A variable of type T is just its value in memory. There is no associated type information (in Go every variable has a single type known at compile time not at run time). It is represented in memory like this:
value
An interface{} holding a variable of type T is represented in memory like this
pointer to type T
value
So coming back to your original question: why go does't implicitly convert []T to []interface{}?
Converting []T to []interface{} would involve creating a new slice of interface {} values which is a non-trivial operation since the in-memory layout is completely different.
Here is the official explanation: https://github.com/golang/go/wiki/InterfaceSlice
var dataSlice []int = foo()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
interfaceSlice[i] = d
}
In Go 1.18 or later, use the following function to convert an arbitrary slice type to []interface{} or its alias any:
func ToSliceOfAny[T any](s []T) []any {
result := make([]any, len(s))
for i, v := range s {
result[i] = v
}
return result
}
The Go 1.18 generics feature does not eliminate the need to convert an arbitrary slice to []any. Here's an example of where the conversion is required: The application wants to query a database using the elements of a []string as the variadic query arguments declared as args ...any. The function in this answer allows the application to query the database in a convenient one-liner:
rows, err := db.Query(qs, ToSliceOfAny(stringArgs)...)
Try interface{} instead. To cast back as slice, try
func foo(bar interface{}) {
s := bar.([]string)
// ...
}
In case you need more shorting your code, you can creating new type for helper
type Strings []string
func (ss Strings) ToInterfaceSlice() []interface{} {
iface := make([]interface{}, len(ss))
for i := range ss {
iface[i] = ss[i]
}
return iface
}
then
a := []strings{"a", "b", "c", "d"}
sliceIFace := Strings(a).ToInterfaceSlice()
I was curious how much slower it is convert interface arrays via reflection vs. doing it inside a loop, as described in Stephen's answer. Here's a benchmark comparison of the two approaches:
benchmark iter time/iter bytes alloc allocs
--------- ---- --------- ----------- ------
BenchmarkLoopConversion-12 2285820 522.30 ns/op 400 B/op 11 allocs/op
BenchmarkReflectionConversion-12 1780002 669.00 ns/op 584 B/op 13 allocs/op
So using a loop is ~20% faster than doing it via reflection.
Here's my test code in case you'd like to verify if I did things correctly:
import (
"math/rand"
"reflect"
"testing"
"time"
)
func InterfaceSlice(slice interface{}) []interface{} {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
// Keep the distinction between nil and empty slice input
if s.IsNil() {
return nil
}
ret := make([]interface{}, s.Len())
for i := 0; i < s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret
}
type TestStruct struct {
name string
age int
}
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func randSeq(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
func randTestStruct(lenArray int, lenMap int) map[int][]TestStruct {
randomStructMap := make(map[int][]TestStruct, lenMap)
for i := 0; i < lenMap; i++ {
var testStructs = make([]TestStruct, 0)
for k := 0; k < lenArray; k++ {
rand.Seed(time.Now().UnixNano())
randomString := randSeq(10)
randomInt := rand.Intn(100)
testStructs = append(testStructs, TestStruct{name: randomString, age: randomInt})
}
randomStructMap[i] = testStructs
}
return randomStructMap
}
func BenchmarkLoopConversion(b *testing.B) {
var testStructMap = randTestStruct(10, 100)
b.ResetTimer()
for i := 0; i < b.N; i++ {
obj := make([]interface{}, len(testStructMap[i%100]))
for k := range testStructMap[i%100] {
obj[k] = testStructMap[i%100][k]
}
}
}
func BenchmarkReflectionConversion(b *testing.B) {
var testStructMap = randTestStruct(10, 100)
b.ResetTimer()
for i := 0; i < b.N; i++ {
obj := make([]interface{}, len(testStructMap[i%100]))
obj = InterfaceSlice(testStructMap[i%100])
_ = obj
}
}
Though you can use a generic function to convert a slice to a slice of interface{}, it may be most appropriate and cheapest in terms of execution time to change foo to a generic function if possible.
For example:
func foo[T any](slice []T) { /* do something */ }
func main() {
var a []string = []string{"hello", "world"}
foo(a)
}
Now there is no conversion necessary at all.
Convert interface{} into any type.
Syntax:
result := interface.(datatype)
Example:
var employee interface{} = []string{"Jhon", "Arya"}
result := employee.([]string) //result type is []string.
I'm curious why Go does't implicitly convert []T to []interface{} when it will implicitly convert T to interface{}. Is there something non-trivial about this conversion that I'm missing?
Example:
func foo([]interface{}) { /* do something */ }
func main() {
var a []string = []string{"hello", "world"}
foo(a)
}
go build complains
cannot use a (type []string) as type []interface {} in function argument
And if I try to do it explicitly, same thing: b := []interface{}(a) complains
cannot convert a (type []string) to type []interface {}
So every time I need to do this conversion (which seems to come up a lot), I've been doing something like this:
b = make([]interface{}, len(a), len(a))
for i := range a {
b[i] = a[i]
}
Is there a better way to do this, or standard library functions to help with these conversions? It seems kind of silly to write 4 extra lines of code every time I want to call a function that can take a list of e.g. ints or strings.
In Go, there is a general rule that syntax should not hide complex/costly operations.
Converting a string to an interface{} is done in O(1) time. Converting a []string to an interface{} is also done in O(1) time since a slice is still one value. However, converting a []string to an []interface{} is O(n) time because each element of the slice must be converted to an interface{}.
The one exception to this rule is converting strings. When converting a string to and from a []byte or a []rune, Go does O(n) work even though conversions are "syntax".
There is no standard library function that will do this conversion for you. Your best option though is just to use the lines of code you gave in your question:
b := make([]interface{}, len(a))
for i := range a {
b[i] = a[i]
}
Otherwise, you could make one with reflect, but it would be slower than the three line option. Example with reflection:
func InterfaceSlice(slice interface{}) []interface{} {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
// Keep the distinction between nil and empty slice input
if s.IsNil() {
return nil
}
ret := make([]interface{}, s.Len())
for i:=0; i<s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret
}
The thing you are missing is that T and interface{} which holds a value of T have different representations in memory so can't be trivially converted.
A variable of type T is just its value in memory. There is no associated type information (in Go every variable has a single type known at compile time not at run time). It is represented in memory like this:
value
An interface{} holding a variable of type T is represented in memory like this
pointer to type T
value
So coming back to your original question: why go does't implicitly convert []T to []interface{}?
Converting []T to []interface{} would involve creating a new slice of interface {} values which is a non-trivial operation since the in-memory layout is completely different.
Here is the official explanation: https://github.com/golang/go/wiki/InterfaceSlice
var dataSlice []int = foo()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
interfaceSlice[i] = d
}
In Go 1.18 or later, use the following function to convert an arbitrary slice type to []interface{} or its alias any:
func ToSliceOfAny[T any](s []T) []any {
result := make([]any, len(s))
for i, v := range s {
result[i] = v
}
return result
}
The Go 1.18 generics feature does not eliminate the need to convert an arbitrary slice to []any. Here's an example of where the conversion is required: The application wants to query a database using the elements of a []string as the variadic query arguments declared as args ...any. The function in this answer allows the application to query the database in a convenient one-liner:
rows, err := db.Query(qs, ToSliceOfAny(stringArgs)...)
Try interface{} instead. To cast back as slice, try
func foo(bar interface{}) {
s := bar.([]string)
// ...
}
In case you need more shorting your code, you can creating new type for helper
type Strings []string
func (ss Strings) ToInterfaceSlice() []interface{} {
iface := make([]interface{}, len(ss))
for i := range ss {
iface[i] = ss[i]
}
return iface
}
then
a := []strings{"a", "b", "c", "d"}
sliceIFace := Strings(a).ToInterfaceSlice()
I was curious how much slower it is convert interface arrays via reflection vs. doing it inside a loop, as described in Stephen's answer. Here's a benchmark comparison of the two approaches:
benchmark iter time/iter bytes alloc allocs
--------- ---- --------- ----------- ------
BenchmarkLoopConversion-12 2285820 522.30 ns/op 400 B/op 11 allocs/op
BenchmarkReflectionConversion-12 1780002 669.00 ns/op 584 B/op 13 allocs/op
So using a loop is ~20% faster than doing it via reflection.
Here's my test code in case you'd like to verify if I did things correctly:
import (
"math/rand"
"reflect"
"testing"
"time"
)
func InterfaceSlice(slice interface{}) []interface{} {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
// Keep the distinction between nil and empty slice input
if s.IsNil() {
return nil
}
ret := make([]interface{}, s.Len())
for i := 0; i < s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret
}
type TestStruct struct {
name string
age int
}
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func randSeq(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
func randTestStruct(lenArray int, lenMap int) map[int][]TestStruct {
randomStructMap := make(map[int][]TestStruct, lenMap)
for i := 0; i < lenMap; i++ {
var testStructs = make([]TestStruct, 0)
for k := 0; k < lenArray; k++ {
rand.Seed(time.Now().UnixNano())
randomString := randSeq(10)
randomInt := rand.Intn(100)
testStructs = append(testStructs, TestStruct{name: randomString, age: randomInt})
}
randomStructMap[i] = testStructs
}
return randomStructMap
}
func BenchmarkLoopConversion(b *testing.B) {
var testStructMap = randTestStruct(10, 100)
b.ResetTimer()
for i := 0; i < b.N; i++ {
obj := make([]interface{}, len(testStructMap[i%100]))
for k := range testStructMap[i%100] {
obj[k] = testStructMap[i%100][k]
}
}
}
func BenchmarkReflectionConversion(b *testing.B) {
var testStructMap = randTestStruct(10, 100)
b.ResetTimer()
for i := 0; i < b.N; i++ {
obj := make([]interface{}, len(testStructMap[i%100]))
obj = InterfaceSlice(testStructMap[i%100])
_ = obj
}
}
Though you can use a generic function to convert a slice to a slice of interface{}, it may be most appropriate and cheapest in terms of execution time to change foo to a generic function if possible.
For example:
func foo[T any](slice []T) { /* do something */ }
func main() {
var a []string = []string{"hello", "world"}
foo(a)
}
Now there is no conversion necessary at all.
Convert interface{} into any type.
Syntax:
result := interface.(datatype)
Example:
var employee interface{} = []string{"Jhon", "Arya"}
result := employee.([]string) //result type is []string.