funcmakeslice(et *_type, len, capint)unsafe.Pointer { mem, overflow := math.MulUintptr(et.size, uintptr(cap)) if overflow || mem > maxAlloc || len < 0 || len > cap { // 先判断是否越界 mem, overflow := math.MulUintptr(et.size, uintptr(len)) if overflow || mem > maxAlloc || len < 0 { panicmakeslicelen() } panicmakeslicecap() }
// 内存分配 return mallocgc(mem, et, true) }
出于好奇看了一下 MaxUintptr 的源码:
// Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
package math
import"runtime/internal/sys"
const MaxUintptr = ^uintptr(0)
// MulUintptr returns a * b and whether the multiplication overflowed. // On supported platforms this is an intrinsic lowered by the compiler. funcMulUintptr(a, b uintptr)(uintptr, bool) { if a|b < 1<<(4*sys.PtrSize) || a == 0 { return a * b, false } overflow := b > MaxUintptr/a return a * b, overflow }
由源码可知,MulUintptr 接收两个参数,分别是要分配的类型大小 a 和要分配的数量 b,计算后返回要分配的内存空间以及是否溢出。
为什么说字符只是整数的特殊用例呢?因为在 Go 中,用于表示字符的 byte 和 rune 类型都是整型的别名。在 Go 的源码中我们可以看到:
// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is // used, by convention, to distinguish byte values from 8-bit unsigned // integer values. typebyte = uint8
// rune is an alias for int32 and is equivalent to int32 in all ways. It is // used, by convention, to distinguish character values from integer values. typerune = int32