Search code examples
arraysgommap

Go: how to convert unsafe.Pointer into pointer to array with unknown length?


I am trying to write a Go program which uses mmap to map a very large file containing float32 values into memory. Here is my attempt (inspired by a previous answer, error handling omitted for brevity):

package main

import (
    "fmt"
    "os"
    "syscall"
    "unsafe"
)

func main() {
    fileName := "test.dat"
    info, _ := os.Stat(fileName)
    fileSize := info.Size()
    n := int(fileSize / 4)

    mapFile, _ := os.Open(fileName)
    defer mapFile.Close()
    mmap, _ := syscall.Mmap(int(mapFile.Fd()), 0, int(fileSize),
        syscall.PROT_READ, syscall.MAP_SHARED)
    defer syscall.Munmap(mmap)
    mapArray := (*[n]float32)(unsafe.Pointer(&mmap[0]))

    for i := 0; i < n; i++ {
        fmt.Println(mapArray[i])
    }
}

This fails with the following error message:

./main.go:21: non-constant array bound n

Since n is determined by the length of the file (not known at compile time), I cannot replace n with a constant value in the cast. How do I convert mmap into an array (or slice) of float32 values?


Solution

  • You first convert to an array of a type with a static length that can fit your data, then slice that array to the correct length and capacity.

    mapSlice := (*[1 << 30]float32)(unsafe.Pointer(&mmap[0]))[:n:n]