Hi,

We'd like to do a zero-copy conversion of []byte to []uint64 where the 
underlying memory for the byte slice is properly aligned for N uint64 
values.  After looking at (6) in the unsafe package documentation 
<https://golang.org/pkg/unsafe/#Pointer>, I'm wondering if the code below 
is valid because I only use reflect.SliceHeader as pointers, and it seems 
to fit pattern 6.

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

package main

import (
"fmt"
"reflect"
"unsafe"
)

func byteToUint64(b []byte) (out []uint64, err error) {
inhdr := *(*reflect.SliceHeader)(unsafe.Pointer(&b))
if inhdr.Len % 8 != 0 {
err = fmt.Errorf("cannot convert non-aligned []byte length (%d) to 
[]uint64", inhdr.Len)
return
}
if inhdr.Cap % 8 != 0 {
err = fmt.Errorf("cannot convert non-aligned []byte capacity (%d) to 
[]uint64", inhdr.Cap)
return
}
outhdr := *(*reflect.SliceHeader)(unsafe.Pointer(&out))
outhdr.Len = inhdr.Len / 8
outhdr.Cap = inhdr.Cap / 8
outhdr.Data = inhdr.Data
out = *(*[]uint64)(unsafe.Pointer(&outhdr))
return
}

func main() {
b := make([]byte, 24)
u, err := byteToUint64(b)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("b: %v\n", b)
fmt.Printf("u: %v\n", u)
fmt.Printf("len(u) = %d, cap(u) = %d\n", len(u), cap(u))
u[0] = 15
fmt.Printf("Set u[0] to 15\n")
fmt.Printf("b: %v\n", b)
fmt.Printf("u: %v\n", u)
u[2] = 255
fmt.Printf("Set u[2] to 255\n")
fmt.Printf("b: %v\n", b)
fmt.Printf("u: %v\n", u)
}
}

Outputs:

b: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
u: [0 0 0]
len(u) = 3, cap(u) = 3
Set u[0] to 15
b: [15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
u: [15 0 0]
Set u[2] to 255
b: [15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0]
u: [15 0 255]


-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to