返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

2. 类型

发布于 2024-10-12 19:15:46 字数 4507 浏览 0 评论 0 收藏 0

基础类型是构成复杂用户类型的基础,由此定义变量、常量及字面量。

变量

关键字 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文