GoLang补充提升(二)
1.Slice切片的截取问题
- 数组是值传递
- 切片是引用传递
- 切片本质上是数组中截取的一段
- 创建切片时会底层自动创建数组
- 当在不扩容的情况下,可以改变底层数组来使切片的值改变,反之亦然
func main() {
arr := [...]int{1, 2, 3, 4, 5, 6, 7}
fmt.Println(arr)
s1 := arr[0:4]
s2 := arr[1:4]
fmt.Println(s1)
fmt.Println("len:", len(s1), "cap:", cap(s1)) //4,7
fmt.Println(s2)
fmt.Println("len:", len(s2), "cap:", cap(s2)) //3,6
arr[2] = 999
fmt.Println(s1)
fmt.Println(s2)
fmt.Printf("%p\n", &arr)
fmt.Printf("%p\n", s1) //和arr的地址相同,因为是从头进行截取的
fmt.Printf("%p\n", s2) //和arr的地址不同,因为不是从头进行截取的
fmt.Println("========================")
s3 := arr[1:3]
fmt.Println(s3)
s3[0] = 666
fmt.Println(arr)
arr[2] = 10101
fmt.Println(s3)
fmt.Println("=========================")
fmt.Println(arr) //[1 666 10101 4 5 6 7]
fmt.Println(s1) //[1 666 10101 4]
fmt.Println(s2) //[666 10101 4]
fmt.Printf("%p\n", s2)
s2 = append(s2, 100, 200, 300, 400, 500) //这里添加的元素使切片进行了扩容,所以地址要发生改变
fmt.Printf("%p\n", s2)
//产生的疑问?那还能操控之前的arr数组了嘛,或者还能收到arr数组值的变话了嘛
//结果显而易见,操作的地址都不同了当然不能影响了
fmt.Println(s2)
arr[0] = 996
fmt.Println(s2)
s2[0] = 87878
fmt.Println(s2)
fmt.Println(arr)
}
2.Slice切片的append删除元素
- 将切片中的某个数删除时(如下方式删除,通过截取删除),底层数组不变
func main() {
x := [...]int{1, 2, 3, 4}
s1 := x[:]
fmt.Println(x)
s1 = append(s1[:1], s1[2:]...)
fmt.Println(s1)
fmt.Println(len(s1))
fmt.Println(cap(s1))
fmt.Println(x) //底层数组的值会覆盖,从而满足切片的需求
}
3.defer 经典案例
执行的顺序
- 1.先对返回值赋值
- 2.执行defer
- 3.真正返回
func main() {
fmt.Println(f1()) //5
fmt.Println(f2()) //6
fmt.Println(f3()) //5
fmt.Println(f4()) //5
fmt.Println(f5()) //6
}
func f1() int {
x := 5
defer func() {
x++
}()
return x
}
func f2() (x int) {
defer func() {
x++
}()
return 5
}
func f3() (y int) {
x := 5
defer func() {
x++
}()
return x
}
func f4() (x int) {
defer func(x int) {
x++
}(x)
return 5
}
func f5() (x int) {
defer func(x *int) {
*x++
}(&x)
return 5
}
4.defer面试题
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
x := 1
y := 2
defer calc("AA", x, calc("A", x, y))
x = 10
defer calc("BB", x, calc("B", x, y))
y = 20
}
5.闭包
(1)事例1
func main() {
f1 := adder(10)
fmt.Println(f1(10)) //20
fmt.Println(f1(20)) //40
fmt.Println(f1(30)) //70
f2 := adder(20)
fmt.Println(f2(10)) //30
fmt.Println(f2(20)) //50
fmt.Println(f2(30)) //80
}
func adder(x int) func(int) int {
return func(y int) int {
x += y
return x
}
}
(2)事例2
func main() {
txtFunc := makeSuffixFunc(".txt")
pngFunc := makeSuffixFunc(".png")
fmt.Println(txtFunc("zzs"))
fmt.Println(pngFunc("ywj"))
}
func makeSuffixFunc(suffix string) func(string) string {
return func(name string) string {
if strings.HasSuffix(name, suffix) {
return name
} else {
return name + suffix
}
}
}
(3)事例3
func main() {
f1, f2 := calc(10)
fmt.Println(f1(1), f2(2)) //11 9
fmt.Println(f1(3), f2(4)) //12 8
}
func calc(base int) (f1, f2 func(int) int) {
f1 = func(i int) int {
base += i
return base
}
f2 = func(i int) int {
base -= i
return base
}
return
}