欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Go基础编程实践(七)—— 并发

程序员文章站 2022-05-23 19:21:36
同时运行多个函数 观察常规代码和并发代码的输出顺序。 通道的关闭 Go // 生产者关闭通道 package main import ( "time" "fmt" ) func main() { channel := make(chan string) go func() { names := [] ......

同时运行多个函数

观察常规代码和并发代码的输出顺序。

// 常规代码,顺序执行,依次输出
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)
    }
}