Please take a look at the following code:

```go
package main

import (
    "fmt"
    "runtime"
    "unsafe"
)

func assert(b bool) {
    if b {
    } else {
        panic("unexpected")
    }
}

type Elementer interface {
    GetInt64Slice() []int64
    GetByteSlice() []byte
    String() string
}

type Element1 struct {
    int64s []int64
    bs     []byte
}

func newElement1(int64Sz, bsSz int) *Element1 {
    assert(int64Sz > 0 && bsSz > 0)
    len0 := int64Sz * 8
    len1 := bsSz
    buf := make([]byte, len0+len1)
    for i := range buf {
        buf[i] = byte(i)
    }
    e := &Element1{
        int64s: unsafe.Slice((*int64)(unsafe.Pointer(&buf[0])), int64Sz),
        bs:     unsafe.Slice((*byte)(&buf[len0]), bsSz),
    }
    return e
}

func (e *Element1) GetInt64Slice() []int64 {
    return e.int64s
}

func (e *Element1) GetByteSlice() []byte {
    return e.bs
}

func (e *Element1) String() string {
    return fmt.Sprintf("Element1:[% x % x]", e.GetInt64Slice(), 
e.GetByteSlice())
}

type Element2 struct {
    underlyBuf []byte  // <- is this field needed?
    int64s     []int64
    bs         []byte
}

func newElement2(int64Sz, bsSz int) *Element2 {
    assert(int64Sz > 0 && bsSz > 0)
    len0 := int64Sz * 8
    len1 := bsSz
    buf := make([]byte, len0+len1)
    for i := range buf {
        buf[i] = byte(i)
    }
    e := &Element2{
        underlyBuf: buf,   // <-
        int64s:     unsafe.Slice((*int64)(unsafe.Pointer(&buf[0])), 
int64Sz),
        bs:         unsafe.Slice((*byte)(&buf[len0]), bsSz),
    }
    return e
}

func (e *Element2) GetInt64Slice() []int64 {
    runtime.KeepAlive(e.underlyBuf)
    return e.int64s
}

func (e *Element2) GetByteSlice() []byte {
    runtime.KeepAlive(e.underlyBuf)
    return e.bs
}

func (e *Element2) String() string {
    runtime.KeepAlive(e.underlyBuf)
    return fmt.Sprintf("Element2:[% x % x]", e.GetInt64Slice(), 
e.GetByteSlice())
}

func main() {
    var e Elementer
    fmt.Println("print with host endian:")
    e = newElement1(2, 4)
    fmt.Println("hi", e)
    e = newElement2(2, 4)
    fmt.Println("hi", e)
}
```

And which yields:

```
hi Element1:[[ 706050403020100  f0e0d0c0b0a0908] 10 11 12 13]
hi Element2:[[ 706050403020100  f0e0d0c0b0a0908] 10 11 12 13]
```

I'm not sure whether the `underlyBuf` filed in `Element2` is needed or not. 
When I'm reading the doc from `https://pkg.go.dev/reflect#SliceHeader` 
there is:

> Moreover, the Data field is not sufficient to guarantee the data it 
references will not be garbage collected, so programs must keep a separate, 
correctly typed pointer to the underlying data.

But in `https://pkg.go.dev/unsafe#Slice` there are no such comments. So the 
question:

Which implementation of `Elementer` is correct? `Element2` or both of them?

Thanks a lot for your help.

-- 
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 golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/5da1eda9-536a-4553-8405-0551792ae449n%40googlegroups.com.

Reply via email to