Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Size in bytes of the content of a slice

Tags:

slice

go

I am trying to send some data to OpenGl. Sending an array is easy thanks to Sizeof:

array := [...]Whatever {lots of data}
array_ptr := gl.Pointer(&array[0])
array_size := gl.Sizeiptr(unsafe.Sizeof(array))
gl.BufferData(gl.ARRAY_BUFFER, array_size, array_ptr, gl.STATIC_DRAW)

I would like to use slices instead of arrays because the size of my 3D models is not known at compile time.

How do I retrieve the size, in bytes, of the content of a slice? I thought of this:

size := uintptr(len(slice)) * unsafe.Sizeof(slice[0])

but it is not very general. Indeed, I need to know the underlying type of the slice in order for this to work, and this supposes that all the elements of the array have the same size.

I could also loop over the whole slice and add all the sizes of every element. It's not very fast.

I am ready to always keep the len(s)==cap(s), can that help me?

Edit: implementation of the proposed solution using runtime reflection

package main

import "fmt"
import "reflect"

func ElemSize(container interface{}) uintptr {
    return reflect.TypeOf(container).Elem().Size()
}
func ElemSizeVerbose(container interface{}) uintptr {
    t := reflect.TypeOf(container)
    e := t.Elem()
    s := e.Size()
    fmt.Println(t, e, s)
    return s
}
func main() {
    a := [...]int8{2, 3, 5, 7, 11} // Array
    s := []int64{2, 3, 5, 7, 11} // Slice
    z := []int32{} // Even empty things
    ElemSizeVerbose(a) // [5]int8 int8 1
    ElemSizeVerbose(s) // []int64 int64 8
    ElemSizeVerbose(z) // []int32 int32 4
}
like image 614
Niriel Avatar asked Feb 04 '13 23:02

Niriel


People also ask

What is the slice size?

A slice has both a length and a capacity. The length of a slice is the number of elements it contains. The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice. The length and capacity of a slice s can be obtained using the expressions len(s) and cap(s) .

What is a slice of byte?

Byte slices are a list of bytes that represent UTF-8 encodings of Unicode code points . Taking the information from above, we could create a byte slice that represents the word “Go”: bs := []byte{71, 111}

How do you measure the length of a slice?

To get length of slice in Go programming, call len() function and pass the slice as argument to it. len() function returns an integer, the length of slice. The function returns an integer value, representing the length of given slice.

What is a slice data type?

Slice is a variable-length sequence which stores elements of a similar type, you are not allowed to store different type of elements in the same slice. It is just like an array having an index value and length, but the size of the slice is resized they are not in fixed-size just like an array.


2 Answers

In a slice or array, every element is always the same size. Therefore, your example will work as long as len(s) > 0. In other words, as long as the slice has at least one element in it. Otherwise it will panic.

To avoid the need of having an element in the slice, I recommend using the following:

 uintptr(len(s)) * reflect.TypeOf(s).Elem().Size()
like image 79
Stephen Weinberg Avatar answered Sep 18 '22 12:09

Stephen Weinberg


you can use (size) of the encoding/binary package.

package main

import (
    "encoding/binary"
    "fmt"
)

func main() {
    a := [...]int8{2, 3, 5, 7, 11} // Array
    s := []int64{2, 3, 5, 7, 11}   // Slice
    z := []int32{}                 // Even empty things

    fmt.Println(binary.Size(a)) // 5
    fmt.Println(binary.Size(s)) // 40
    fmt.Println(binary.Size(z)) // 0
}
like image 22
Daniel Castillo Avatar answered Sep 19 '22 12:09

Daniel Castillo