if判断
if条件判断有一种特殊的写法:在 if 表达式之前添加一个执行语句,再根据变量值进行判断。
if score := 65; score >= 90 {
}
switch
与 Java中的 switch 相比,go 中 switch 除了被用作“选择”,还可用作“判断”,即多重if-else判断。
func unhex(c byte) byte {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
for循环
for循环常用的三种表现形式:
// 类似 C 语言中的 for 用法
for init; condition; post { }
// 类似 C 语言中的 while 用法
for condition { }
// 类似 C 语言中的 for(;;) 用法
for { }
for-range
使用for range遍历数组、切片、字符串、map 及通道(channel)。
- 数组、切片、字符串返回索引和值。
- map返回键和值。
- 通道(channel)只返回通道内的值。
切片(slice)
切片对数组进行封装,这里的封装是指可以将切片看作是特殊的结构体,结构体中包含数组指针(即地址)、长度和容量。
type Slice struct {
ptr *T
len, cap int
}
slice 本身不会存储任何数据,slice 通过指针指向底层数组的某一个位置,这个位置就是 slice 的初始位置。长度表示当前 slice 中的元素个数,容量表示从指针的位置到底层数组的最后一个位置。
“切片保存了对底层数组的引用,若你将某个切片赋予另一个切片,它们会引用同一个数组。 若某个函数将一个切片作为参数传入,则它对该切片元素的修改对调用者而言同样可见, 这可以理解为传递了底层数组的指针。” 引自《Effective Go》
如果想复制切片,但又不想改动原切片,可用内建函数 copy():
copy(destSlice, srcSlice)
基于数组创建切片,并带初始化元素:
numslice := []int{1, 2, 3}
通过 make 构建一个长度为10,容量为100的切片,会自动填充零值。
make([]int, 10, 100)
如果判断一个切片是否是空的,应使用 len(s)== 0 来判断,不应使用 s == nil 来判断。
var s1 []int //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{} //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil
映射
键-值对。其键可以是任何相等性操作符支持的类型, 如整数、浮点数、复数、字符串、指针、接口(只要其动态类型支持相等性判断)、结构以及数组。 切片不能用作映射键,因为它们的相等性还未定义。与切片一样,映射也是引用类型。 若将映射传入函数中,并更改了该映射的内容,则此修改对调用者同样可见。
var timeZone = map[string]int{
"UTC": 0*60*60,
"EST": -5*60*60,
"CST": -6*60*60,
"MST": -7*60*60,
"PST": -8*60*60,
}
赋值和获取映射值的语法类似于数组,不同的是映射的索引不必为整数。不过不存在会返回0。 为了区分0和数据不存在两种情况,可以通过布尔来接收数据是否存在。
v := timeZone["UTC"]
v, ok := timeZone["UTC"]
要删除映射中的某项,可使用内建函数 delete,它以映射及要被删除的键为实参。 即便对应的键不在该映射中,此操作也是安全的。
delete(timeZone, "PDT")
追加
内建函数append,可以同时为切片追加多个参数。
arr := []string{"123", "456"}
str := "789"
arr = append(arr, str) //数据也是一种切片,默认容量=长度+1
除使用append外,还可以通过改变指针的位置来改变 slice 的长度;
arr2 := arr[1:2]
fmt.Println(len(arr2)) // 1
fmt.Println(cap(arr2)) // 3