Go中切片的最大长度 [英] Maximum length of a slice in Go

查看:314
本文介绍了Go中切片的最大长度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在4Gb机器上的64位linux操作系统中运行以下代码:

  package main 

导入(
fmt
数学


func main(){
r:= make([] bool ,math.MaxInt32)

fmt.Println(Size:,len(r))
}

当我运行这个时,我得到:

 大小:2147483647 

如果我为 math.MaxInt32 > math.MaxUint32 我得到:

 致命错误:运行时:内存不足

切片大小 math.MaxUint32 内存不足,我在等待,但当我尝试使用 math.MaxInt64 时,我得到:

  panic:runtime error:makelice:len超出范围

所以我无法创建一个切片大小为 math.MaxInt64 ,这将我们带入我的问题:如果内存不是一个我记得在Java中,原始数组索引是通过类型 int 来管理的, / code>,所以原始数组的最大大小是 int 的最大值,如果你试图用 long 它会引发一个异常(据我记忆),Go跟它一样吗?是切片索引在Go绑定到一个特定类型?



编辑:



我使用 struct {} 而不是 bool 并分配 math.MaxInt64 元素。一切都如预期,并打印:

 大小:9223372036854775807 

$ b b $ b

弹出每个错误的条件是什么? 根据文档,元素可以通过整数索引0到len(s)-1 来寻址。这意味着切片的最大容量是目标版本上默认整数的大小。



编辑:从源代码看,它有一个安全检查,以确保切片的大小尽可能:

  func makeslice(t * slicetype,len64 int64,cap64 int64)sliceStruct {
//注意:len> MaxMem / elemsize这里检查不是必须的,
//但它会产生一个'len超出范围'的错误,而不是'cap out of range'错误
//当有人确定make([]) T,bumberumber)。 '超出范围'也是如此,
//但由于只能隐含提供上限,所以说len更清晰。
//见issue 4085.
len:= int(len64)
如果len64< 0 || int64(len)!= len64 || t.elem.size> 0&& uintptr(len)> maxmem / uintptr(t.elem.size){
panic(errorString(makelice:len out of range))
}

所以在这种情况下,它看起来像 uintptr(len)> maxmem / uintptr(t.elem.size)所以我们不允许做这样大小的分配。



然而,当我分配 struct {} 它不需要内存,这个尺寸是允许的:

  func main(){
r:= make([] struct {},math.MaxInt64)
fmt.Println(len(r))
}
//打印9223372036854775807


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?

解决方案

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

这篇关于Go中切片的最大长度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆