GOLANG面试八股文-Go语言的 44.5个预定义标识符、用法和变量屏蔽

与作为语法保留字的 25 个关键字(Keywords)不同,预定义标识符(Predeclared Identifiers) 是 Go 编译器在全局作用域中预先声明好的名称。你可以把它们当成 Go 自动为你免费导入的“全局常识”。值得注意的是:从语法层面上,它们可以被重新声明(覆盖/Shadowing),但极度不推荐这么做。

早期文章中流传的 “36个预定义标识符” 实际上随着GOLANG自身版本更新目前已经增至 44 个,加上用于忽略返回值的下划线“_”,勉强算半个,总共44.5个。

下面将详细街上 44 个 预定义标识符的完整分类与详细用法:

一、内建常量(4 个)

表示基本逻辑字面量、零值以及编译期枚举计数器。

1. true:布尔类型真的字面量,无类型(Untyped)。
2. false:布尔类型假的字面量,无类型。
3. nil:预定义的零值。代表指针(pointer)、通道(channel)、函数(function)、接口(interface)、映射(map)或切片(slice)这些引用和高级数据类型的“空”状态。
4. iota:常量生成器(计数器)。只能在 const 声明块中使用。在遇到 const 关键字时它被置为 0,块中每新增一行常量声明,它的值就自动加 1。常用于go中定义枚举。

二、内建数据类型(22 个)

表示计算机底层的数据结构抽象。

1. 基础型 (2个)

5. bool:布尔类型,值只能是 true 或者 false。
6. string:不可变的字节序列封装(默认以 UTF-8 编码表示文本)。

2. 无符号整型(按系统架构与特定位长,6个)

7. uint:自动匹配当前操作系统的位数(32位系统为4字节,64位系统为8字节)。
8. uint8:8位无符号整型,表示范围 0 ~ 255。
9. uint16:16位无符号整型。
10. uint32:32位无符号整型。
11. uint64:64位无符号整型。
12. uintptr:无符号整型,其设计目的是大小刚好能保存一个指针的值。它通常在 unsafe 包进行底层内存计算时充当指针与整数之间的桥梁。

3. 有符号整型(5个)

13. int:最常用的普通整型,长度随操作系统架构变化(类似 uint)。
14. int8:8位有符号整型,表示范围 -128 ~ 127。
15. int16:16位有符号整型。
16. int32:32位有符号整型。
17. int64:64位有符号整型。

4. 浮点与复数型(4个)

18. float32:单精度浮点数。
19. float64:双精度浮点数(默认的小数类型,精度更安全)。
20. complex64:复数类型,实部和虚部均由 float32 构成。
21. complex128:复数类型,实部和虚部均由 float64 构成。

5. 类型别名与接口(3个)

22. byte:等同于 uint8,这是 Go 的内置的类型别名。专门用来强调正在处理的数据是原始字节流而不是数学意义上的数字。
23. rune:等同于 int32,内置类型别名。专门用于表示一个 Unicode 码点(即单个字符)。
24. error:内置接口类型,用于标准错误处理。其底层定义为 interface { Error() string }。

6. 泛型相关(2个)

25. any:本质上就是 interface{} 的别名。自从引入泛型后,它代替了过去代码中大量出现的空接口,不仅在泛型约束中可用,普通代码中用来表示“任意类型”也更加语义化。
26. comparable:只用于泛型类型约束的接口类型。若一个泛型参数受到 comparable 约束,则意味着这种类型可以使用 == 和 != 进行比较操作(例如用作 map 的 key 类型)。

三、内建函数(18 个)

这些函数由编译器直接支持,属于底层基本操作。使用时无需特别 import。

1. 结构初始化相关 (2个)

27. make:专门用来初始化并分配内存给切片(slice)、映射(map)、通道(channel)。返回值是对象本身。
28. new:能够为任意类型分配内存并将内存空间清零,返回值是指向这块内存的指针(*T)。

2. 切片、Map 与 Channel 管理 (5个)

29. len:获取集合的元素长度(适用于 string, array, slice, map, channel)。
30. cap:获取底层容器的最大容量(适用于 array, slice, channel)。
31. append:给切片追加一个或多个元素,底层会在容量不足时自动扩容,必须用原来的切片接收它的返回值。
32. copy:在两个切片之间拷贝数据。拷贝数量由较短的切片长度决定。
33. delete:从 map 中删除指定键值的元素。
34. close:关闭 channel,表示不再向通道内发送数据,否则引发 panic,但通道内残留的数据依然可以被接收者读取。
35. clear:极度强力的辅助语法。它可以清空 Map 中的所有键值对,或者将 Slice 内部的所有元素直接“归零”(设为对应类型的 Zero Value,但不缩短切片的 len)。

3. 错误捕获控制流程 (2个)

36. panic:立刻终止当前函数的正常执行流程,并开始逐层向上“恐慌”崩溃(向调用堆栈抛出异常),如果到了顶层还没被处理,程序就会退出。
37. recover:必须配合 defer 语句使用。用于在 panic 发生的“坠机”过程中截获恐慌值并恢复程序,让程序继续正常存活下去。

4. 底层打印 (2个)

38. print:将参数写入标准错误输出(stderr)。
39. println:自带换行并加入参数间空格的底层打印。 (⚠️ 这两个打印函数主要供编译器和底层运行时(runtime)在 fmt 包还无法加载时的自举和调试用,日常业务开发应全部使用 fmt.Print / fmt.Println。)

5. 数学及复数运算 (3个)

40. complex:将两部分实数拼接、构造出一个复数。
41. real:提取复数中的实部。
42. imag:提取复数中的虚部。
43. max:返回传入的多个参数(必须同类型或可比类型)中的最大值(泛型支持)。告别了以前只能自己写或者用 math.Max(float, float) 的尴尬。
44. min:返回多个参数中的最小值(泛型支持)。

四、变量屏蔽(Shadowing)

什么是 Shadowing(变量屏蔽)?
请看下面这段完全可以顺利编译通过且正常运行,但有可能让同事对你进行真人快打的代码:

1
2
3
4
5
6
7
func disaster() {
    var true = false
    var int = 10
    len := 5

    fmt.Println(true, int, len) // false 10 5
}

这就是预定义标识符区别于关键字 (if / for / func 等) 的最大特征:关键字在任何时刻都不允许做变量名,而预定义标识符允许。

这 44.5个名字,是咱们编写 Go 代码时心里最重要的“保留词库”,应当当作伪关键字来对待,绝对不要占用它们!

发表回复

Your email address will not be published. Required fields are marked *.

*
*