同时运行多个函数
观察常规代码和并发代码的输出顺序。
// 常规代码,顺序执行,依次输出
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)
}
}