一些简单的总结
- 哪些种类型的值可以有间接底层部分?
- 各种容器类型比较
- 各种类型的尺寸
- 我们可以为什么样的类型声明方法?
- 哪些函数调用将在编译时刻被估值?
- 哪些类型不支持比较?
- 哪些有名代码元素可多个被一起声明在一对小括号()中?
- 哪些表达式的估值结果可以包含一个额外的可选的值?
- 几种衔接字符串的方法
在Go中,下列种类的类型的值可以有间接底层部分:
- 字符串类型
- 函数类型
- 切片类型
- 映射类型
- 通道类型
- 接口类型
注意:此答案基于标准编译器的实现。事实上,函数类型的值是否有间接底层部分是难以证明的。 另外,字符串和接口类型的值在逻辑上应该被认为是不含间接底层部分。 请阅读获取更多信息。
哪些种类型的值可以用做内置len
(以及cap
、close
、delete
和make
)函数调用的实参?
可以被用做内置函数len
调用的参数的值的类型都可以被称为(广义上的)容器类型。 这些容器类型的值都可以跟在for-range
循环的range
关键字后。
各种容器类型比较
类型 | 容器值是否支持添加新的元素? | 容器值中的元素是否可以被替换? | 容器值中的元素是否可寻址? | 访问容器值元素是否会更改容器长度? | 容器值是否可以有间接底层部分? |
---|---|---|---|---|---|
字符串 | 否 | 否 | 否 | 否 | 是(1) |
数组 | 否 | 是(2) | 是(2) | 否 | 否 |
切片 | 否(3) | 是 | 是 | 否 | 是 |
映射 | 是 | 是 | 否 | 否 | 是 |
通道 | 是(4) | 否 | 否 | 是 | 是 |
(1) 对于标准编译器和运行时来说。
(2) 对于可寻址的数组值来说。
(3) 一般说来,一个切片的长度只能通过将另外一个切片赋值给它来被整体替换修改,这里我们不视这种情况为“添加新的元素”。 其实,切片的长度也可以通过调用reflect.SetLen
来单独修改。增加切片的长度可以看作是一种变相的向切片添加元素。 但reflect.SetLen
函数的效率很低,因此很少使用。
(4) 对于带缓冲并且缓冲未满的通道来说。
哪些种类型的值可以用组合字面量()表示?
下面在四种类型的值(除了切片和映射类型的零值)可以用组合字面量表示。
各种类型的尺寸
详见值复制成本一文。
哪些种类型的零值使用预声明的nil
标识符表示?
下面这些类型的零值可以用预声明的nil
标识符表示。
类型(T ) | T(nil) 的尺寸 |
---|---|
指针 | 1 word |
切片 | 3 words |
映射 | 1 word |
通道 | 1 word |
函数 | 1 word |
接口 | 2 words |
上表列出的尺寸为标准编译器的结果。 一个word(原生字)在32位的架构中为4个字节,在64位的架构中为8个字节。 一个Go值的间接底层部分未统计在尺寸中。
一个类型的零值的尺寸和其它非零值的尺寸是一致的。
什么样的类型可以被内嵌在结构体类型中?
详见一文。
哪些函数调用将在编译时刻被估值?
如果一个函数调用在编译时刻被估值,则估值结果为一个常量。
哪些值是可寻址的?
请阅读此条问答获取详情。
哪些类型不支持比较?
请阅读此条问答获取详情。
哪些代码元素允许被声明却不使用?
允许被声明却不使用? | |
---|---|
包引入 | 不允许 |
类型 | 允许 |
变量 | 包级全局变量允许,但局部变量不允许(对于官方标准编译器)。 |
常量 | 允许 |
函数 | 允许 |
跳转标签 | 不允许 |
下面这些同种类的代码元素可多个被一起声明在一对小括号()
中:
- 包引入
- 类型
- 变量
- 常量
函数是不能多个被一起声明在一对小括号()
中的。跳转标签也不能。
哪些代码元素的声明可以被声明在函数内也可以被声明在函数外?
下面这些代码元素的声明既可以被声明在函数内也可以被声明在函数外:
- 类型
- 变量
- 常量
包引入必须被声明在其它种类的代码元素的声明之前。
函数必须声明在任何函数体之外。匿名函数可以定义在函数体内,但那不属于声明。
哪些表达式的估值结果可以包含一个额外的可选的值?
下列表达式的估值结果可以包含一个额外的可选的值:
几种导致当前协程永久阻塞的方法
无需引入任何包,我们可以使用下面几种方法使当前协程永久阻塞:
向一个永不会被接收数据的通道发送数据。
从一个未被并且将来也不会被发送数据的(并且保证永不会被关闭的)通道读取数据。
从一个nil通道读取或者发送数据。
几种衔接字符串的方法
详见一文。
官方标准编译器中实现的一些优化
详见。
详见。