defer中出现的例子
package main
import "fmt"
type Test struct {
name string
}
func (t *Test) Close() {
fmt.Println(t.name, " closed")
}
func main() {
ts := []Test{{"a"}, {"b"}, {"c"}}
for _, t := range ts {
defer t.Close()
}
}
输出结果:
c closed
c closed
c closed
解决办法
1 多写一层调用
package main
import "fmt"
type Test struct {
name string
}
func (t *Test) Close() {
fmt.Println(t.name, " closed")
}
func Close(t Test) {
t.Close()
}
func main() {
ts := []Test{{"a"}, {"b"}, {"c"}}
for _, t := range ts {
defer Close(t)
}
}
输出结果:
c closed
b closed
a closed
2 写传入参数的闭包
package main
import "fmt"
type Test struct {
name string
}
func main() {
ts := []Test{{"a"}, {"b"}, {"c"}}
for _, t := range ts {
defer func(t Test){
fmt.Println(t.name, " closed")}(t)
}
}
3 重新声明
package main
import "fmt"
type Test struct {
name string
}
func (t *Test) Close() {
fmt.Println(t.name, " closed")
}
func main() {
ts := []Test{{"a"}, {"b"}, {"c"}}
for _, t := range ts {
t := t
defer t.Close()
}
}
channel中的例子
package main
import (
"fmt"
"time"
)
func main() {
info := make(chan string)
go send(info)
for w := range info {
go func() {
time.Sleep(600 * time.Millisecond)
fmt.Println(w)
}()
}
time.Sleep(1000 * time.Millisecond)
}
func send(info chan string) {
word := [...]string{"A", "B", "C", "D", "E", "F"}
for _, s := range word {
info <- s
}
close(info)
}
输出结果:
F
F
F
F
F
F
同样解决方法
1 写传入参数的闭包
package main
import (
"fmt"
"time"
)
func main() {
info := make(chan string)
go send(info)
for w := range info {
go func(w string) {
time.Sleep(600 * time.Millisecond)
fmt.Println(w)
}(w) // 作为实参传入
}
time.Sleep(1000 * time.Millisecond)
}
func send(info chan string) {
word := [...]string{"A", "B", "C", "D", "E", "F"}
for _, s := range word {
info <- s
}
close(info)
}
输出结果:
E
B
A
C
F
D
2 重新声明
package main
import (
"fmt"
"time"
)
func main() {
info := make(chan string)
go send(info)
for w := range info {
w := w
go func() {
time.Sleep(600 * time.Millisecond)
fmt.Println(w)
}()
}
time.Sleep(1000 * time.Millisecond)
}
func send(info chan string) {
word := [...]string{"A", "B", "C", "D", "E", "F"}
for _, s := range word {
info <- s
}
close(info)
}
在defer函数定义时,对外部变量的引用是有两种方式的,分别是作为函数参数和作为闭包引用。
作为函数参数,则在defer定义时就把值传递给defer,并被cache起来;
作为闭包引用的话,则会在defer函数真正调用时根据整个上下文确定当前的值。
defer后面的语句在执行的时候,函数调用的参数会被保存起来,也就是复制了一份。真正执行的时候,实际上用到的是这个复制的变量,因此如果此变量是一个“值”,那么就和定义的时候是一致的。如果此变量是一个“引用”,那么就可能和定义的时候不一致。
defre写闭包需要传入参数