切片
切片分片操作
请问下面go程序的输出结果是什么?
package main
import (
"fmt"
)
func main() {
orderLen := 5
order := make([]uint16, 2*orderLen)
pollorder := order[:orderLen:orderLen]
lockorder := order[orderLen:][:orderLen:orderLen]
fmt.Println("len(pollorder) = ", len(pollorder))
fmt.Println("cap(pollorder) = ", cap(pollorder))
fmt.Println("len(lockorder) = ", len(lockorder))
fmt.Println("cap(lockorder) = ", cap(lockorder))
}
运行结果
len(pollorder) = 5
cap(pollorder) = 5
len(lockorder) = 5
cap(lockorder) = 5
解释:程序中定义一个长度为10的切片order,pollorder和lockorder分别是对order切片做了order[low:high:max]操作生成的切片,最后程序分别打印pollorder和lockorder的容量和长度。order[low:high:max]操作意思是对order进行切片,新切片范围是[low, high),新切片容量是max。order长度为2倍的orderLen,pollorder切片指的是order的前半部分切片,lockorder指的是order的后半部分切片,即原order分成了两段。所以,pollorder和lockerorder的长度和容量都是orderLen,即5。
延迟调用
协程和延迟调用的估值时刻[1]
一个协程调用或者延迟调用的实参是在此调用发生时被估值的。更具体的说:
对于一个延迟函数调用,它的实参是在此调用被推入延迟调用栈的时候被估值的
对于一个协程调用,它的实参是在此协程被创建的时候估值的
一个匿名函数体内的表达式是在此函数被执行的时候才会被逐个估值的,不管此函数是被普通调用还是延迟/协程调用。
package main
import "fmt"
func main() {
func() {
for i := 0; i < 3; i++ {
defer fmt.Println("a:", i)
}
}()
fmt.Println()
func() {
for i := 0; i < 3; i++ {
defer func() {
// 调用时会发生栈逃逸
fmt.Println("b:", i)
}()
}
}()
}
运行结果:
a: 2
a: 1
a: 0
b: 3
b: 3
b: 3
解释,这两种defer调用的区别在于第一个i的值是通过传参获取的,第二个i的值是通过闭包进行传递的。第二个函数退出的时候开始执行defer调用,此时i的值是3,自然三次defer调用输出的值都是3。
参考资料:
[1].协程、延迟函数调用以及恐慌和恢复.https://gfw.go101.org/article/control-flows-more.html
[2].go专家编程