I have the following code running in a 64-bit linux OS in a 4Gb machine:
package main
import (
"fmt"
"math"
)
func main() {
r := make([]bool, math.MaxInt32)
fmt.Println("Size: ", len(r))
}
When I run this I get:
Size: 2147483647
If I change the math.MaxInt32
for math.MaxUint32
I get:
fatal error: runtime: out of memory
With slice size of math.MaxUint32
I ran out of memory, I was expecting that, but when I try using math.MaxInt64
I get:
panic: runtime error: makeslice: len out of range
So aparently I cannot create a slice with a size of math.MaxInt64
, which bring us to my question: If the memory is not an issue, what's the biggest slice I cant create in Go?
I remember that, in Java, raw array indexes are managed with the type int
, so the maximum size of a raw array is the max value of an int
, if you try to do it with long
it will raise an exception (as far as I remember), is it the same with Go? are slice index in Go bound to one specific type?
EDIT:
I ran the test using struct{}
instead of bool
and allocating math.MaxInt64
elements. Everything went as expected, and prints:
Size: 9223372036854775807
So, another question, why there are two different error messages when it seems that the error is the same (not enough memory)?
What are the conditions for each error to pop out?
The length of the slice is 5, which means the total number of elements present in the slice is 5 and the capacity of the slice 6 means it can store a maximum of 6 elements in it.
In Go, the length of a slice tells you how many elements it contains. It can be obtained using the len() function. The capacity is the size of the slice's underlying array and can be obtained with the cap() function.
Use append to increase the length and capacity of a slice The append operation is clever when growing the capacity of the underlying array. For example, the capacity is always doubled when the existing capacity of the slice is under 1,000 elements.
A slice is a data type in Go that is a mutable, or changeable, ordered sequence of elements.
According to the docs, The elements can be addressed by integer indices 0 through len(s)-1
. This means the maximum capacity for a slice is the size of the default integer on the target build.
EDIT: From looking at the source code, it appears that there is a safety check to make sure this size of slice is at all possible:
func makeslice(t *slicetype, len64 int64, cap64 int64) sliceStruct {
// NOTE: The len > MaxMem/elemsize check here is not strictly necessary,
// but it produces a 'len out of range' error instead of a 'cap out of range' error
// when someone does make([]T, bignumber). 'cap out of range' is true too,
// but since the cap is only being supplied implicitly, saying len is clearer.
// See issue 4085.
len := int(len64)
if len64 < 0 || int64(len) != len64 || t.elem.size > 0 && uintptr(len) > maxmem/uintptr(t.elem.size) {
panic(errorString("makeslice: len out of range"))
}
So in this case, it looks like uintptr(len) > maxmem/uintptr(t.elem.size)
so we're not allowed to do this size of an allocation.
However when I allocate struct{}
which takes no memory, this size is allowed:
func main(){
r := make([]struct{}, math.MaxInt64)
fmt.Println(len(r))
}
// prints 9223372036854775807
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With