Go基礎編程實踐(七)—— 併發

同時運行多個函數

觀察常規代碼和併發代碼的輸出順序。併發

// 常規代碼,順序執行,依次輸出
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)
    }
}
相關文章
相關標籤/搜索