Go的变量传参是值传递
这边文章有具体分析:《Go语言参数传递是传值还是传引用》,看一段代码:
1 | package main |
输出:
1 | [1 0 0] |
第二段输出并不是[1 0 0 3 4 5],切片是引用类型,但是并不是引用传递。Go底层中如果切片没有扩容,修改的结果将应用到原值。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## Defer 中包含panic,panic仅有最后一个可以被revover捕获
示例代码:
```go
package main
import (
"fmt"
)
func main() {
defer func() {
// 无法被捕获
panic("defer panic 1")
}()
defer func() {
if err := recover(); err != nil{
fmt.Println("receive: ",err)
}else {
fmt.Println("fatal")
}
}()
defer func() {
// 被recover捕获
panic("defer panic 2")
}()
defer func() {
panic("defer panic 3")
}()
// 这里的会被替换
panic("panic here")
}
defer的执行顺序是先进后出。输出:
1 | receive: defer panic 2 |
触发panic("panic")
后defer顺序出栈执行,第一个被执行的defer中 会有panic("defer panic 3")
异常语句,这个异常将会覆盖掉main中的异常panic("panic")
,第三个defer会替换掉panic(“defer panic 3”),这个异常被第二个执行的defer捕获到。第一个无法被捕获程序崩溃。
Go中可以调用类型赋值为nil的属性方法
1 | package main |
正常输出:
1 | &{} |
程序并不会奔溃。这事什么原因呢?Google中找到一段说明
In Go the function to be called by the Expression.Name() syntax is entirely determined by the type of Expression and not by the particular run-time value of that expression, including nil.
对象方法是不在运行时确定的(编译时已经确定),所以运行时对象的nil,并不会导致panic;
struct{} 是个空类型
struct{} 是个空类型,所有struct{} 指向同一个零地址,可以用于channel的信号传送
1 | package main |
无论执行多少次,同台电脑都会输出相同的值
1 | 0x118e370 |
不要用共享内存进行协程通讯
1 | package main |
该代码运行一段时间后,会panic. 说明string 类型其实不是线程安全的。str内部结构包含len、data 两个字段,先修改了data,在没有修改len情况下,取值将取的是str的len长度的字符串,所以上述代码会panic。当然这也违背了Go语言:”不要通过共享内存来通信,而应该通过通信来共享内存”。