上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
2. 类型
基础类型是构成复杂用户类型的基础,由此定义变量、常量及字面量。
变量
关键字 var
用于定义变量。和 C 不同,类型被放在变量名后。
- 自动初始化为二进制零值(zero value)。
- 显式提供初始值,可省略类型,由编译器推断。
- 同一作用域内不能重复定义。
- 未使用局部变量当做错误。
var x int // 0 var y = false // bool
var max int func main() { // var x int // ~ declared but not used }
可一次定义多个变量,包括用不同初始值定义不同类型。
var ( x, y int // 相同类型 a, s = 100, "abc" // 不同类型 )
简短模式 :(short variable declaration)
- 显式初始化。
- 不能提供类型。
- 仅限函数内部。
func main() { x := 100 a, s := 1, "abc" println(x, a, s) }
func main() { x := 100 if x > 0 { x := "abc" // 定义同名变量! println(&x, x) } println(&x, x) } // 0xc000032760 abc // 0xc000032758 100
简短模式并不总是重新定义,也可能是部分退化的赋值操作。
退化赋值 前提条件: 最少有一个新变量被定义,且必须是同一作用域。
func main() { x := 100 println(&x) x, y := 200, "abc" // x 退化赋值,y 是新变量。 println(&x, x) println(y) } /* 0xc000032768 0xc000032768 200 abc */
func main() { x := 100 println(&x) { // 不同作用域。 x, y := 200, "abc" // 全部新定义。 println(&x, x) println(y) } } /* 0xc000032768 0xc000032760 200 abc */
多变量赋值,先计算出全部右值,然后再依次赋值。
func main() { x, y := 1, 2 x, y = y+3, x+2 println(x, y) // 5, 3 } /* $ go build -gcflags "-N" $ go tool objdump -S -s "main\.main" ./test func main() { x, y := 1, 2 MOVQ $0x1, 0x10(SP) ; x MOVQ $0x2, 0x8(SP) ; y x, y = y+3, x+2 MOVQ 0x10(SP), AX ADDQ $0x2, AX MOVQ AX, 0x18(SP) ; tmp = x + 2 MOVQ 0x8(SP), AX ADDQ $0x3, AX ; AX = y + 3 MOVQ AX, 0x10(SP) ; x = AX MOVQ 0x18(SP), AX MOVQ AX, 0x8(SP) ; y = tmp */
常量
常量表示恒定不变的值,通常是一些字面量。
- 必须是编译期可确定的值。
- 可指定类型,或由编译器推断。
- 不支持字面量类型后缀。(C:
123LL
) - 可在函数内定义。
- 未使用常量不会引发编译错误。
const ( ptrSize = unsafe.Sizeof(uintptr(0)) strSize = len("hello, world!") )
func main() { const x, f = 100, 1.23 { const x = "abc" println(x) } }
如指定类型,须确保值类型一致,可做显式转换。
右值不能超出常量取值范围,否则引发错误。
const ( x, y int = 99, -999 b byte = byte(x) // n = uint8(y) // ~~~~~ cannot convert y (constant -999 of type int) to type uint8 )
在常量组中如不指定类型和初始化值,则其(类型和初始化表达式)与上一常量相同。
func main() { const ( x uint16 = 120 y s = "abc" z ) fmt.Printf("%T, %v\n", y, y) // uint16, 120 fmt.Printf("%T, %v\n", z, z) // string, abc }
枚举
没有明确意义上的枚举类型(enum),借助 iota
自增常量值来实现枚举效果。
const ( x = iota // 0 y // 1 z // 2 ) const ( _ = iota // 0 KB = 1 << (10 * iota) // 1 << (10 * 1) MB // 1 << (10 * 2) GB // 1 << (10 * 3) ) func main() { println(KB, MB) // 1024 1048576 }
自增作用范围为常量组。
可使用多个 iota
,各自单独计数,只须列数相同即可。
const ( _, _ = iota, iota * 10 // 0, 0 * 10 a, b // 1, 1 * 10 c, d // 2, 2 * 10 )
如中断自增,须显式恢复,且后续自增值按行序递增。
const ( a = iota // 0 b // 1 c = 100 // 100 d // 100 (与上一行常量右值表达式相同) e = iota // 4 (恢复 iota 自增,计数包括 c、d 两行) f // 5 )
默认数据类型为 int
,可显式指定。
const ( a = iota // int, 0 b float32 = iota // float32, 1.0 c = iota // int, 2(若没有 iota,则与 b 类型相同) )
用自定义类型实现用途明确的枚举类型。
但不能将取值范围严格限定在预定义的枚举值内。
type color byte const ( black color = iota red blue ) func test(c color) { println(c) } func main() { test(red) const m = 100 test(m) // 无类型常量和字面量不超出 color/byte 取值范围即可。 // const n int = 100 // test(n) // ~ cannot use n (constant 100 of type int) as type color // x := 2 // test(x) // ~ cannot use x (variable of type int) as type color }
命名
选用有实际含义,易于阅读和理解的字母或单词组合。
- 以字母或下划线开始。
- 由字母、数字和下划线组合而成。
- 区分大小写。
- 使用驼峰(camel case)拼写格式。
- 局部变量优先使用短名。
- 不使用保留关键字。
- 不与预定义常量、类型、内置函数同名。
名为 “ _
” 的 空标识符 (blank identifier)是预设成员,不应重新定义。
可用作表达式左值,表示忽略,但无法作右值返回内容。
func main() { x := 100 _ = x // 规避变量未使用错误。 }
空标识符是对编译器的一种建议,提示进行语法检查,但不一定生成对应机器指令。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论