为何Go内置函数len返回类型为int,而非uint?

779 阅读1分钟

主线剧情

在我们写代码的过程中,经常使用到len求集合类型的长度。

func len(v Type) int

那你有没有想过,为何len的返回值类型是int。

要知道golang的数值类型,分为有符号整数和无符号整数类型。

有符号类型:int8/int16/int32/int64

无符号类型:uint8/uint16/uint32/uint64

对于一个集合的长度,肯定是非负数,用uint就行吧~

真的吗?

我们来看一个例子

func main() {
   //
   var nums = []int{1, 2, 3, 4}

   // 倒序遍历数组
   for i := lenUInt(nums) - 1; i >= 0; i-- {
      fmt.Printf("i:%d -> num:%d\n", i, nums[i])
   }
}

// 简单实现一个返回uint的len函数
func lenUInt(v []int) uint {
   return uint(len(v))
}

各位思考一下,上面的代码能够成功执行码?

不能!

i:3 -> num:4
i:2 -> num:3
i:1 -> num:2
i:0 -> num:1
panic: runtime error: index out of range [18446744073709551615] with length 4

因为uint总是大于等于0的,01=23211!=10-1 = 2^{32-1}-1 != -1

0-1不等于-1,遍历永远不会停止,或者panic

这下大家明白了吧。

len返回int而不是uint,是因为uint可能会造成灾难性后果

支线剧情

当然len(v)会根据v的类型,做出不同的回应。

查看golang的官方文档,如下

Array: the number of elements in v.
Pointer to array: the number of elements in *v (even if v is nil).
Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
String: the number of bytes in v.
Channel: the number of elements queued (unread) in the channel buffer;
         if v is nil, len(v) is zero.

参考

f87DVP5soL.jpg