1. 循环体变量
package main
import (
"fmt"
"time"
)
func main(){
tt()
}
func tt() {
for i := 0; i < 10; i++ {
go func() {
time.Sleep(1e3)
fmt.Println(i)
}()
}
time.Sleep(1e9)
}
- 这个函数执行的时候 tt中打印出来的是10
- 原因也是很简单,
- 因为go在初始化的时候先初始化参数量,
- 全局先初始参数再看函数,
- 在函数内部先初始参数再进行运算,
- 所以 就造成在for执行完后,这里的i是同样的i,以为初始化的参数 i一直会变,但是都是这个变量本身,又因为for循环比内部的函数速度快很多,导致,当for循环进行完了,这些函数还没正式开始运行,然后i就取最终值10了
2. return 和 defer 的执行顺序
- 在Go语言的函数中
return
语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。 - 而
defer
语句执行的时机就在返回值赋值操作后,RET指令执行前。
return x
- 返回值 = x
- 运行defer
- RET指令
3. 值的方法和指针的方法
-
指针的方法和值的方法可以互相调用,因为go会自动帮你
- 比如指针的方法g()你使用了值来调用那么go会帮你自动取地址相对的如果是 值的方法 go自动帮你取 *
-
值上面可以有方法 指针上面也是有方法,我们谈的是 关于对象的方法这点先阐述 因为除了struct(对象)其它类型除了 指针和nil都可以有自己的方法 其它类型不讨论
-
就是指针的方法的时候,那么go会自动帮你取这个对象的,因为指针没办法取得对象 里面的value值,只能去得到,但是go帮你取了,所以你可以使用看似指针直接去值。
4.关于range使用的是复制值的
package main
import "fmt"
func main() {
a := []int{1, 2, 3}
for k, v := range a {
// range后面的a 是对于 上面的a的复制值 ,但是由于slice底层array连带变了,所以v值就会产生变化
if k == 0 {
a[0], a[1] = 100, 200
fmt.Print(a)
}
a[k] = 100 + v
}
fmt.Print(a)
a1 := [3]int{1, 2, 3}
for k, v := range a1 {
// 这里的a1 是上面a1的复制值,所以v永远就跟之前的那个样子一样,纵然 真实的a1发生了变化但是复制值是不会变化的
if k == 0 {
a1[0], a1[1] = 100, 200
fmt.Print(a1)
}
a1[k] = 100 + v
}
}
//[100 200 3][101 300 103][100 200 3]
5.简式声明仅可以在函数内部使用
package main
myvar := 1 //error
func main() {
}
6.array 函数的参数
Go
中的数组是数值,因此当你向函数中传递数组时,函数会得到原始数组数据的一份复制。如果你打算更新数组的数据,这将会是个问题。
package main
import "fmt"
func main() {
x := [3]int{1,2,3}
func(arr [3]int) {
arr[0] = 7
fmt.Println(arr) //prints [7 2 3]
}(x)
fmt.Println(x) //prints [1 2 3] (not ok if you need [7 2 3])
}
如果你需要更新原始数组的数据,你可以使用数组指针类型。
package main
import "fmt"
func main() {
x := [3]int{1,2,3}
func(arr *[3]int) {
(*arr)[0] = 7
fmt.Println(arr) //prints &[7 2 3]
}(&x)
fmt.Println(x) //prints [7 2 3]
}
另一个选择是使用 slice
。即使你的函数得到了 slice
变量的一份拷贝,它依旧会参照原始的数据。
package main
import "fmt"
func main() {
x := []int{1,2,3}
func(arr []int) {
arr[0] = 7
fmt.Println(arr) //prints [7 2 3]
}(x)
fmt.Println(x) //prints [7 2 3]
}
7.在 slice 和 array 使用“range”语句时的出现的不希望得到的值
Bad:
package main
import "fmt"
func main() {
x := []string{"a","b","c"}
for v := range x {
fmt.Println(v) //prints 0, 1, 2
}
}
Good:
package main
import "fmt"
func main() {
x := []string{"a","b","c"}
for _, v := range x {
fmt.Println(v) //prints a, b, c
}
}