Go 语言进阶 | 青训营笔记

44 阅读1分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

1.语言进阶

Go可以充分发挥多核优势,高效运行
多线程程序在单核cpu上并发运行
多线程程序在多核cpu上并行运行

Goroutine

用Go语言快速打印0~4(并发编程goroutine)
goroutine是建立在线程上的轻量级的抽象,它允许我们以非常低的代价在同一个地址空间中并行的执行多个函数或者方法,相比于线程,它的创建和销毁代价小很多,并且它的调度室独立于线程的。在golang中使用go关键字创建一个goroutine。

package main

import (
	"fmt"
	"time"
)

func main() {
	for i := 0; i < 5; i++ {
		go func(j int) {
			fmt.Println(j)
		}(i)
	}
	time.Sleep(time.Second)
}

运行结果

image.png 至于为什么每次打印的数字都不一样呢,这是因为非单核处理并且内存逃逸

Channel

本质上就实现角度来讲,golang 的 channel 就是一个环形队列(ringbuffer)的实现。我们称 chan 为管理结构,channel 里面可以放任何类型的对象,我们称之为元素。 我们从宏观的 chan 使用姿势入手,总结来讲,有以下几种姿势:

  • chan 的创建
  • chan 入队
  • chan 出队
  • select 和 chan 结合
  • for-range 和 chan 结合 chan 的创建
// 无缓冲通道的 channel
c := make(chan int)
// 有缓冲通道的 channel
c1 := make(chan int, 10)

chan 入队

c <- x

chan 出队

val := <- c
val,ok := <- c

select 和 chan 结合

select {
case c <- x:
 //  ... foo
default:
 //  ... bar
}
select {
case val := <- c:
 //  ... foo
default:
 //  ... bar
}
select {
case val,ok := <- c:
 //  ... foo
default:
 //  ... bar
}

for-range 和 chan 结合

for i:= range c {
    // ...   do something
}

例: A子协程发送0~50数字
B子协程计算输入数字乘上5
主协程输出最后得数 代码

package main

import (
   "fmt"
)

func main() {
   input := make(chan int)
   output := make(chan int, 5)
   go func() {
      defer close(input)
      for i := 0; i <= 50; i++ {
         input <- i
      }
   }()
   go func() {
      defer close(output)
      for i := range input {
         output <- i * 5
      }
   }()
   for i := range output {
      fmt.Println(i)
   }
}

运行结果 image.png