基本数据类型&标识符
- 不允许将数组定义为常量
- 常量标识符无法取址
_
为匿名标识符,不能被使用,只能被赋值- 关于iota定义常量的知识点
2 * iota
可以设置常量为偶数索引
go
const (
a = iota // == 0
b // == 1
c // == 2
d = 567 // iota被打断
e // == 567
f = iota // == 6 还是从最开始计数
g // == 7
)
const (
a = 123
b // == 123
c // == 123
d = 567
e // == 567
f = iota // == 5 仍旧从开头计数
// 如果想从0开始,那就减去5:iota - 5
g // == 6
)
- 双引号
"abc"
是字符串string;单引号'a'
是rune类型,仅能为一个字符 - 可以通过
b, c = c, b
来交换变量,前提是类型相同
选择&分支&循环
- Go1.22后循环体中的循环变量的生命周期仅存在当前循环的一趟中
- for-range语句对字符串遍历会按照单个字符遍历,而不是for语句的按照字节遍历
数组&切片
- go语言的数组元素可变但是长度是不可变的,长度和容量也是相同的,其中元素可被索引,是顺序表存储结构
- 定义数组的时候必须明确大小,后续无法更改
var b [3]int
的类型是[3]int
,意为长度和容量为3的数组类型arr := [2][3]int{}
这个二维数组中第一维的类型就是[3]int
- 数组的地址就是数组中首元素的地址
a2 := a1
数组的拷贝就是值拷贝,创建完整的副本&a[0]
取的是数组中第一个元素的地址;(&a)[0]
是取这个数组的索引值,等价于a[0]
- 切片是顺序表,线性结构,采用和数组一样的访问方式
var s1 []int
和s2 := []int{}
不一样,前者没有建立底层的数据结构但是后者有,前者的指针是指向0地址的s3 := make(type, len, cap)
容量cap必须>长度len- 切片扩容实际上是新建一个相同的容量更大的数组
- 用切片赋值给新切片只复制Header副本,实际上共用同个底层数组;方法传参切片也只是复制Header
- 切片索引右边界缺省值是长度,最大值是容量
字符串数组
字符串数组比较特殊,内部每个元素不是直接存储字符串内容,而是存储了内容的元数据和指向内存中另一部分的字符串的指针,元数据表示有多长,真正存储的内容在别的内存空间中,所以字符串数组不管每个元素的大小差别有多大,间隔的内存地址还是一样长的 以下是字符串本身的源码,需要注意的是字符串本身就是一个常量,也是不可变的!
go
type string struct {
Data uintptr // 指向实际字符串数据的指针
Len int // 字符串的长度
}