栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么Go中有数组?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么Go中有数组?

数组不仅仅是固定长度,还有更多:它们是
可比较的
,并且它们是
(不是引用或指针类型)。

在某些情况下,数组比切片有无数的优势,所有这些优点加在一起证明了数组的存在(以及切片)。让我们看看他们。(我什至不算数组是切片的基础。)


1. 具有可比性意味着 您可以将数组用作地图中的键 ,但不能 用作
切片。是的,您现在可以说为什么不让切片具有可比性,因此仅凭这一点并不能证明两者均存在。切片上没有很好地定义平等。常见问题解答:为什么地图不允许切片作为键?

他们没有实现平等,因为在此类类型上对平等的定义不明确。有多种考虑因素,包括浅层比较与深层比较,指针与值比较,如何处理递归类型等等。

2. 数组还可以为您提供更高的编译时安全性
,因为可以在编译时检查索引范围(数组长度必须计算为一个可以由type值表示的非负常量

int
):

s := make([]int, 3)s[3] = 3 // "Only" a runtime panic: runtime error: index out of rangea := [3]int{}a[3] = 3 // Compile-time error: invalid array index 3 (out of bounds for 3-element array)

3. 同样, 传递或分配数组值也将隐式创建 整个数组 的副本 ,因此它将与原始值“分离”。如果您传递一个切片,它将仍然仅复制切片
标头
,但切片值(标头)将指向相同的后备数组。这可能是您想要的,也可能不是。如果要从“原始”切片“分离”切片,则必须显式复制内容,例如使用内置

copy()
函数复制到新切片。

a := [2]int{1, 2}b := ab[0] = 10 // This only affects b, a will remain {1, 2}sa := []int{1, 2}sb := sasb[0] = 10 // Affects both sb and sa

4. 同样,由于数组长度是数组类型的一部分,所以 长度不同的数组是不同的类型
。一方面,这可能是“痛苦中的事情”(例如,编写一个带有类型参数的函数

[4]int
,您不能使用该函数来处理和处理类型数组
[5]int
),但这也可能是一个优势:可以用于
显式指定 所需数组 的长度
。例如,您想编写一个使用IPv4地址的函数,可以使用type对其进行建模
[4]byte
。现在,您有了编译时的保证,即传递给您的函数的值将恰好具有4个字节,不多也不少(无论如何这都是无效的IPv4地址)。

5. 与之前的内容有关, 数组长度也可以用于记录目的
。类型

[4]byte
正确记录了IPv4有4个字节。一个
rgb
类型的可变
[3]byte
告诉有对每个颜色成分1个字节。在某些情况下,甚至可以将其取出并单独记录;例如在
crypto/md5
包中:
md5.Sum()
返回类型为的值,
[Size]byte
其中
md5.Size
一个常数为
16
:MD5校验和的长度。

6.计划结构类型的内存布局
时,它们也非常有用,请参阅此处的JimB答案,以及更多详细信息和实际示例。

7. 同样,由于切片是标头,并且它们(几乎)总是按原样传递(没有指针), 因此语言规范对切片的指针比对数组的指针更具限制性
。例如,规范提供了多个用于操作数组指针的简写,而在切片时会给出编译时错误(因为很少使用指向切片的指针,如果仍然需要/必须这样做,则必须明确处理;)

这样的例子是:

  • 分割

    p
    指向array:的指针
    p[low:high]
    是的简写
    (*p)[low:high]
    。如果
    p
    是指向slice的指针,则为编译时错误(规范:slice表达式)。

  • 索引

    p
    数组指针:
    p[i]
    是的简写
    (*p)[i]
    。如果
    p
    is是指向切片的指针,则这是编译时错误(规范:Index expressions)。

例:

pa := &[2]int{1, 2}fmt.Println(pa[1:1]) // OKfmt.Println(pa[1])   // OKps := &[]int{3, 4}println(ps[1:1]) // Error: cannot slice ps (type *[]int)println(ps[1])   // Error: invalid operation: ps[1] (type *[]int does not support indexing)

8. 访问(单个)数组元素 比访问切片元素 更有效 ;像分片一样,运行时必须经过隐式指针取消引用。另外, “如果表达式
的类型是数组或指向数组的指针,则表达式

len(s)
cap(s)
为常量
s

可能令人惊讶,但您甚至可以写:

type IP [4]byteconst x = len(IP{}) // x will be 4

它是有效的,即使

IP{}
不是常量表达式,
consti = IP{}
也要进行评估和编译时,因此例如将是编译时错误!在此之后,以下操作也就不足为奇了:

const x2 = len((*IP)(nil)) // x2 will also be 4

注意:在一个完整的数组与一个完整的切片之间进行测量时,可能根本没有性能上的差异,因为显然可以对其进行优化,以使切片头中的指针仅被取消引用一次。有关详细信息/示例,请参阅数组与切片:访问速度。


必须阅读的博客:

切成薄片:用法和内部原理

数组,切片(和字符串):“追加”的机制



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/368930.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号