【问题标题】:Finding the maximum length value of a collection that can be declared in golang using make()使用 make() 查找可以在 golang 中声明的集合的最大长度值
【发布时间】:2016-11-16 11:06:35
【问题描述】:

我在创建动态数组时遇到错误“恐慌:运行时错误:makelice:len 超出范围”,使用“make()”获取较大的长度值。

例如。

arr := make([]int, length)   //length is a dynamic value

我知道,这个问题已经在这里问过了 (Maximum length of a slice in Go)。 但是,make 方法不支持 golang 中“int”数据类型的最大值。它们使用基于结构类型(大小)的长度值。 是否有任何预定义的 API 可用于查找可以在 golang 中声明的集合的最大长度值?

例如:

maxInt := int(^uint(0) >> 1) 

arr := make([]struct{}, maxInt-1)  //accepted
arr := make([]int, maxInt-1)  //throw error

【问题讨论】:

  • @Volker 对于您的问题,是的!这是可行的。 Golang 使用函数 maxSliceCap[go1.7/src/runtime/slice.go:32] 验证 len 和 cap。有一些 API 可以获取运行时信息。虽然这可以通过使用 defer 函数来捕获恐慌和恢复来实现,但我们可以使用一个简单明了的 API。问题是是否有任何公开的 API 会有所帮助。
  • @Spartan 这只是 hard upper limits!不能保证实际上会有足够的空闲内存来分配这个片。 _MaxMem 不是实际可用的,甚至不是实际存在的 RAM。但你是对的:如果这是 OP 的问题,那么我的立场是正确的。

标签: go


【解决方案1】:

如果你真的想要切片的最大长度,你可以从运行时包中复制使用的算法。这将以切片元素的示例来确定其大小,并返回该值类型的最大切片容量。

func maxSliceCap(i interface{}) int {
    _64bit := uintptr(1 << (^uintptr(0) >> 63) / 2)

    var goosWindows, goosDarwin, goarchArm64 uintptr
    switch runtime.GOOS {
    case "darwin":
        goosDarwin = 1
    case "windows":
        goosWindows = 1
    }

    switch runtime.GOARCH {
    case "arm64":
        goarchArm64 = 1
    }

    heapMapBits := (_64bit*goosWindows)*35 + (_64bit*(1-goosWindows)*(1-goosDarwin*goarchArm64))*39 + goosDarwin*goarchArm64*31 + (1-_64bit)*32
    maxMem := uintptr(1<<heapMapBits - 1)

    elemSize := reflect.ValueOf(i).Type().Size()
    max := maxMem / elemSize

    if int(max) < 0 {
        return 1<<31 - 1
    }

    return int(max)
}

https://play.golang.org/p/roOarwQpZL

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-10
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多