For循环中用的变量是复用的,配合闭包,启用goroutine的时候要特别小心。
func main() {
for i := 0 ; i < 4; i++ {
//time.Sleep(time.Nanosecond)
go func() {
print(i)
}()
}
time.Sleep(time.Second)
}
result:4444
package main
import "time"
func main() {
for i := 0 ; i < 4; i++ {
time.Sleep(time.Nanosecond)
go func() {
print(i)
}()
}
time.Sleep(time.Second)
}
result: 1234
例1,当四个routine起来的时候,i已经被赋值为4,4个routine传入的是统一个i,所以打印出4444。
例2,起每个routine前都sleep一会,也就是当前routine起来时,前一个已经起来,并完成打印。所以打印1234。
一个简单的framework for a rate-limited, parallel, non-blocking RPC system, and there's not a mutex in sight,client,server例子。
package main
//import "time"
import "fmt"
type Request struct {
args []int
f func([]int) int
resultChan chan int
}
func main() {
request1 := &Request{[]int{3, 4, 5}, sum, make(chan int)}
request2 := &Request{[]int{6, 7, 8}, sum, make(chan int)}
// Send request
// clientRequests := make(chan *Request) leads to deadlock
clientRequests := make(chan *Request, 2)
clientRequests <- request1
clientRequests <- request2
// Wait for response.
go func(queue chan *Request) {
for req := range queue {
// in the same routine, next line is not necessary
//req := req
req.resultChan <- req.f(req.args)
}
}(clientRequests)
fmt.Printf("answer: %d\n", <-request1.resultChan)
fmt.Printf("answer: %d\n", <-request2.resultChan)
}
func sum(a []int) (s int) {
for _, v := range a {
s += v
}
return
}
main相当于client,新开的routine相当于server。
package main
import "fmt"
func sum(m map[int]int) {
m[0] = 1
}
func main() {
m := make(map[int]int)
sum(m)
fmt.Println(m[0]) // 1
}
package main
import "fmt"
func fn(m map[int]int) {
m = make(map[int]int)
}
func main() {
var m map[int]int
fn(m)
fmt.Println(m == nil) // true
}
例1说明map是通过reference的方式传递,
为什么例2会返回true
可以reference传递的前提是已经有分配内存,nil的时候无法reference吗?