制作容量小于长度的切片
package main import fmt "fmt" func main(){ type b []int var k = make([]b, 10, 5) fmt.Printf("%d\n",k[8]) }
尝试运行时会出现以下错误。
panic: runtime error: makeslice: cap out of range runtime.panic+0x9e /go/src/pkg/runtime/proc.c:1060 runtime.panic(0x453b00, 0x30020390) runtime.panicstring+0x94 /go/src/pkg/runtime/runtime.c:116 runtime.panicstring(0x4afd6c, 0x40d80c) runtime.makeslice+0x70 /go/src/pkg/runtime/slice.c:24 runtime.makeslice(0x44302c, 0xa, 0x0, 0x5, 0x0, ...) main.main+0x45 C:/GOEXCE~1/basics/DATATY~1/slice.go:8 main.main() runtime.mainstart+0xf 386/asm.s:93 runtime.mainstart() runtime.goexit /go/src/pkg/runtime/proc.c:178 runtime.goexit() ----- goroutine created by ----- _rt0_386+0xbf 386/asm.s:80
我的问题是容量是否小于长度?
如果'是'那么为什么会出现这个错误?
如果'不是为什么这是一个运行时错误,为什么不是编译时?
答案 0 :(得分:13)
不,容量不能小于长度。
切片是对数组的一部分的引用。切片的容量表示该后备阵列的大小。如果它的长度大于它的容量,那么它使用的内存是什么?
以下不变量总是适用于切片s(除非你做了不安全的事情):
0 <= len(s) <= cap(s)
您的代码会产生运行时错误而不是编译时错误,因为无法始终静态检测错误。在你的情况下它可能是,但考虑这个代码:
package main
import (
"fmt"
"rand"
)
func main() {
k := make([]int, rand.Int(), rand.Int())
fmt.Println(k)
}
传递给make的值在运行时才能知道。
答案 1 :(得分:4)
阅读Go Programming Language Specification。
切片的容量是存在的元素数 在底层数组中分配的空间。随时有以下情况 关系成立:
0 <= len(s) <= cap(s)
答案 2 :(得分:0)
检查runtime/slice.go
func makeslice(et *_type, len, cap int) unsafe.Pointer {
mem, overflow := math.MulUintptr(et.size, uintptr(cap))
if overflow || mem > maxAlloc || len < 0 || len > cap {
// NOTE: Produce 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 golang.org/issue/4085.
mem, overflow := math.MulUintptr(et.size, uintptr(len))
if overflow || mem > maxAlloc || len < 0 {
panicmakeslicelen()
}
panicmakeslicecap()
}
return mallocgc(mem, et, true)
}
它会检查 len 和 cap,如果 len<0 或 len>cap 会报错。