1

I have slices of different types, and I need to send them with TCP. The length of my slices is large, and not a constant value. Is there any way that I can convert the slices into []byte without looping through individual elements? For example, I want something like this (assuming mySlice elements are 4 Bytes here):

byteSlice := (*[4 * len(mySlice)]byte)(unsafe.Pointer(&mySlice[0]))

but it won't work, since 4 * len(mySlice) is not a constant.

Thank you.

Ari
  • 23
  • 4
  • did you get it to work with a sample where the size is known? – TehSphinX Aug 09 '17 at 17:21
  • @TehSphinX , I didn't try it, and I am not sure if that is a good way even if the size was known. In my case the size need to be calculated, and is always unknown in advance. – Ari Aug 09 '17 at 17:29
  • just wondering if you had solved the second part already... – TehSphinX Aug 09 '17 at 17:34
  • 1
    I don't know the details, of course, but it seems like you might be better off serializing your data using protobuf or something similar. Sending the raw bytes that make up some Go type isn't portable. – Andy Schweig Aug 09 '17 at 18:05
  • 1
    Or [`gob`](https://golang.org/pkg/encoding/gob/), which is more efficient than protobuf but less flexible and less interoperable. – Adrian Aug 09 '17 at 18:07
  • 1
    It shouldn't work. Messing around with memory in go is not a good practice. Use some serialization package to do this instead. The performance gain from unsafe casting cannot justify the fact that this may introduce memory leak/corruption. – xiaoyi Aug 09 '17 at 23:08

2 Answers2

0

So this is what I ended up doing (posting it as an answer to my question):

import "unsafe"
import "reflect"   

mySliceR := *(*reflect.SliceHeader)(unsafe.Pointer(&mySlice))
mySliceR.Len *= mySliceElemSize
mySliceR.Cap *= mySliceElemSize

byteSlice := *(*[]byte)(unsafe.Pointer(&mySliceR))

I tested it for different array sizes, and it is better than looping through individual elements (using only unsafe.Pointer) only when arrays are large enough.

Ari
  • 23
  • 4
  • From the description of [`reflect.SliceHeader`](https://golang.org/pkg/reflect/#SliceHeader): "It cannot be used safely or portably and its representation may change in a later release." This is a very fragile implementation, and nonsensical to anyone else who reads it - why not just use a proper encoding like `gob`? – Adrian Aug 10 '17 at 13:35
-1

In your sample code you're creating arrays, not slices, hence the error. To create a slice of a specific length, use make, which does not require the length to be a constant. When you create an array, the length must be a constant, because you're creating an unnamed type which must be resolvable at compile time.

Adrian
  • 42,911
  • 6
  • 107
  • 99