2

The Mmap() syscall in the x/sys/unix package in Golang returns a []byte type, while the underlying syscall actually returns a pointer. How does it do this?

More specifically, in this package by a Golang developer, the VirtualAlloc function simply returns a pointer. How can this be converted to a byte slice, the same way as it's done in the Unix package?

Awn
  • 817
  • 1
  • 16
  • 33
  • 4
    Try this https://github.com/golang/sys/blob/d75a52659825e75fff6158388dddc6a5b04f9ba5/unix/syscall_unix.go#L72-L80 ([Playground example](https://play.golang.org/p/An7jG5xl2W)) – mkopriva Apr 24 '17 at 14:44
  • @mkopriva Wow, can't believe I missed that. Could you post that as an answer? – Awn Apr 24 '17 at 15:39
  • the comment is now posted as an answer. – mkopriva Apr 24 '17 at 15:50

3 Answers3

5

Using the unsafe package you could do something similar to what's being done in the Mmap method's unix implementation:

type sliceHeader struct {
    addr unsafe.Pointer
    len int
    cap int
}

var b []byte
hdr := (*sliceHeader)(unsafe.Pointer(&b))
hdr.addr = unsafe.Pointer(addr)
hdr.cap = length
hdr.len = length

Here's a playground example.

mkopriva
  • 35,176
  • 4
  • 57
  • 71
  • 1
    There is an error in this solution. Since `uintptr` has no [pointer semantics](https://golang.org/pkg/unsafe/#Pointer), this pointer may be collected by the GC, leading to incredibly hard bugs. The `addr` field should have the `unsafe.Pointer` type, as seen [here](https://golang.org/pkg/internal/unsafeheader/#Slice). – rodrigocfd Jun 18 '21 at 00:07
5

As of Go 1.17, you can now use unsafe.Slice:

mySlice := unsafe.Slice(ptr, numElements)
rodrigocfd
  • 6,450
  • 6
  • 34
  • 68
3

You could use something like C.GoBytes (e.g. see here):

// C data with explicit length to Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084