观察常规代码和并发代码的输出顺序。并发
// 常规代码,顺序执行,依次输出 package main import ( "fmt" "time" ) func main() { strN := []string{"a", "b", "c", "d"} for _, strV := range strN { time.Sleep(time.Second) fmt.Println(strV) } intN := []int{1, 2, 3, 4} for _, intV := range intN { time.Sleep(time.Second) fmt.Println(intV) } }
// 并发代码,并发执行,无序输出 package main import ( "fmt" "time" ) func main() { go func() { strN := []string{"a", "b", "c", "d"} for _, strV := range strN { time.Sleep(time.Second) fmt.Println(strV) } }() go func() { intN := []int{1, 2, 3, 4} for _, intV := range intN { time.Sleep(time.Second) fmt.Println(intV) } }() // 防止main routine过早退出 time.Sleep(10 * time.Second) }
// 生产者关闭通道 package main import ( "time" "fmt" ) func main() { channel := make(chan string) go func() { names := []string{"Jack", "Mike", "John", "Kitty"} for _, name := range names { time.Sleep(time.Second) // fmt.Println(name) channel <- name } // 发送完毕关闭通道,不然引发死锁 close(channel) }() for data := range channel { fmt.Println(data) } }
// 利用无缓冲通道同步传递数据 package main import "fmt" func main(){ nameChannel := make(chan string) done := make(chan string) go func(){ names := []string {"tarik", "michael", "gopi", "jessica"} for _, name := range names { fmt.Println("Processing the first stage of: " + name) nameChannel <- name } close(nameChannel) }() go func(){ for name := range nameChannel{ fmt.Println("Processing the second stage of: " + name) } done <- "" }() <-done }
// 利用有缓冲通道传递数据,提升性能 package main import "fmt" func main(){ nameChannel := make(chan string, 5) done := make(chan string) go func(){ names := []string {"tarik", "michael", "gopi", "jessica"} for _, name := range names { fmt.Println("Processing the first stage of: " + name) nameChannel <- name } close(nameChannel) }() go func(){ for name := range nameChannel{ fmt.Println("Processing the second stage of: " + name) } done <- "" }() <-done }
package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { // 遍历一次,增长一次计数 wg.Add(1) go func(){ fmt.Println("Hello World") // 执行一次,减小一次计数 wg.Done() }() } // 等待计数归零,结束程序 wg.Wait() }
// 利用通道等待 package main import ( "time" "fmt" ) func main() { channel := make(chan string) go func() { names := []string{"Jack", "Mike", "John", "Kitty"} for _, name := range names { time.Sleep(time.Second) fmt.Println(name) // channel <- name } // 遍历完毕向通道发送数据,告诉main routine已执行完毕 channel <- "" }() // main routine收到数据,退出程序 // 由于只是为了同步,不须要通道中的数据,因此将数据抛弃 <-channel }
package main import ( "time" "fmt" ) func main() { channel1 := make(chan string) channel2 := make(chan string) go func(){ time.Sleep(1*time.Second) channel1 <- "Hello from channel1" }() go func(){ time.Sleep(1 * time.Second) channel2 <- "Hello from channel2" }() var result string // select随机选择知足条件的case select { case result = <-channel1: fmt.Println(result) case result = <-channel2: fmt.Println(result) } }