-
Notifications
You must be signed in to change notification settings - Fork 0
/
demo.go
221 lines (196 loc) · 3.32 KB
/
demo.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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package main
import (
"context"
"fmt"
"log"
"os"
"runtime"
unsafe "unsafe"
)
// 注意参数展开的问题。
func m1() {
var a = []interface{}{1, 2, 3}
fmt.Println(a)
fmt.Println(a...)
/**
1. [1 2 3]
2. 1 2 3
*/
}
// 数组是值传递,无法通过修改数组类型的参数返回结果。
func m2() {
x := [3]int{1, 2, 3}
func(arr [3]int) {
arr[0] = 7
fmt.Println(arr)
}(x)
fmt.Println(x)
/**
[1, 2, 3]
*/
}
// map是一种hash表实现,每次遍历的顺序都可能不一样。
func m3() {
m := map[string]string{
"1": "1",
"2": "2",
"3": "3",
}
for k, v := range m {
println(k, v)
}
}
// recover必须在defer中执行
func m4() {
//defer recover()
//panic(1) error
//defer func() {
// func() {
// recover()
// }()
//}()
//panic(1) error
defer func() {
recover()
}()
panic(1)
}
// 避免独占CPU Goroutine是协作式抢占调度,Goroutine本身不会主动放弃CPU
func m5() {
// 1
runtime.GOMAXPROCS(1)
//go func() {
// for i := 0; i < 10; i++ {
// fmt.Println(i)
// }
//}()
//for {
// runtime.Gosched()
//}
// 2
go func() {
for i := 0; i < 10; i++ {
fmt.Println(i)
}
os.Exit(0)
}()
select {}
}
// 闭包错误引用同一个变量
func m6() {
//for i := 0; i < 3; i++ {
// defer func() {
// println(i)
// }()
//}
// error
// 3, 3, 3
//for i := 0; i < 3; i++ {
// defer func(i int) {
// println(i)
// }(i)
//}
// correct
// 0, 1, 2
}
// defer在函数退出时才能执行,在for执行defer会导致资源延迟释放
func m7() {
for i := 0; i < 3; i++ {
f, err := os.Open("path")
if err != nil {
log.Fatal(err)
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
}
}(f)
} //error
for i := 0; i < 3; i++ {
func() {
f, err := os.Open("path")
if err != nil {
log.Fatal(err)
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
}
}(f)
}()
} // correct
}
// 切片会导致整个底层数组被锁定,无法释放内存。
func m8() {
headerMap := make(map[string][]byte)
for i := 0; i < 3; i++ {
name := "/path"
data, err := os.ReadFile(name)
if err != nil {
log.Fatal(err)
}
// headerMap[name] = data[:1] error
headerMap[name] = append([]byte{}, data[:1]...) // correct
}
}
// 对象的地址可能发生变化,因此指针不能从其它非指针类型的值生成
func m9() {
var x int = 32
var p uintptr = uintptr(unsafe.Pointer(&x))
runtime.GC()
var px *int = (*int)(unsafe.Pointer(p))
println(*px)
// 当内存发送变化的时候,相关的指针会同步更新,但是非指针类型的uintptr不会做同步更新。
// 同理CGO中也不能保存Go对象地址。
}
func m10() {
//ch := func() <-chan int {
// ch := make(chan int)
// go func() { // 无法回收
// for i := 0; ; i++ {
// ch <- i
// }
// }()
// return ch
//}()
//
//for v := range ch {
// fmt.Println(v)
// if v == 5 {
// break
// }
//}
ctx, cancel := context.WithCancel(context.Background())
ch := func(ctx context.Context) <-chan int {
ch := make(chan int)
go func() {
for i := 0; ; i++ {
select {
case <-ctx.Done():
return
case ch <- i:
}
}
}()
return ch
}(ctx)
for v := range ch {
fmt.Println(v)
if v == 5 {
break
}
}
cancel()
}
func main() {
m1()
m2()
m3()
m4()
m5()
m6()
m7()
m8()
m9()
m10()
}