> 協程是Go語言的關鍵特性,主要用于并發編程,協程是一種輕量級的線程,因為協程開銷比較小,所以創建上萬的協程也不是什么難事
[TOC]
## 創建并運行協程
> 通過go關鍵詞創建一個協程
```
go dotest()
```
> 例子
> go攜程特性:當主攜程退出后,子攜程隨之退出
```
package main
import (
"fmt"
"strconv"
"time"
)
// 定義一個函數,循環打印5次字符串
func say(name string) {
for i := 0; i < 5; i++ {
// 當前協程休眠1秒
time.Sleep(1000 * time.Millisecond)
fmt.Println(name + strconv.FormatInt(int64(i), 10))
}
}
// 程序啟動的時候,首先創建一個主協程,運行main函數
func main() {
// 創建一個協程,運行say函數,傳入參數"wk"
go say("wk")
// 在主協程中運行say函數,傳入參數"jiaojiao"
go say("jiaojiao")
// 以下代碼,設置無線循環,可組織主攜程退出
/*for {
;
}*/
}
```
> 以上例子,wk和jiaojiao交叉輸出,但是有可能say("jiaojiao")函數先執行完成,主程就會退出,導致say("wk")函數的攜程沒有執行完畢就終止了。
> 解決這種問題,就需要用到`channel通信`,如下
~~~
package main
import "fmt"
func doubleNum(num int, c chan int) {
c <- num * 2
}
func main() {
// 定義一個無緩沖區的channel,用來接收協程計算結果
channel := make(chan int)
// 創建第1協程
go doubleNum(3, channel)
// 創建第2個協程
go doubleNum(2, channel)
// 使用channel讀取,會進行阻塞,直到有數據后,才會往下執行
x := <-channel
y := <-channel
// 打印計算結果,主程退出
fmt.Println(x, y, x+y)
}
~~~
## 協程通信
> 協程之間通信主要有兩種方式
> * [共享全局變量](https://www.tizi365.com/archives/457.html):因為協程本身是在同一個進程中運行,所以可以共享變量,但是為了解決并發問題,保證數據原子性,需要加鎖處理。
> * channel:管道通信,避免復雜的加鎖操作(下篇將進行介紹)
- 基礎知識
- 開發環境
- 包名規則
- 包初始化 (init)
- 基礎數據類型
- 基礎類型轉換
- 格式化輸出
- go指針
- 流程控制語句
- 函數定義
- 匿名函數
- 數組和切片
- map集合
- 結構體
- Interface接口
- 日期處理
- 數學計算
- 正則表達式
- 協程 (并發處理)
- channel
- waitgroup
- mutex (鎖機制)
- websocket
- protobuf
- Redis
- 錯誤處理
- 打包程序
- NSQ消息隊列
- 單元測試
- beego
- 安裝入門
- Gin
- 快速入門
- 路由與控制器
- 處理請求參數
- 表單驗證
- 處理響應結果
- 渲染HTML模版
- 訪問靜態文件
- Gin中間件
- Cookie處理
- Session處理
- Gin上傳文件
- swagger
- pprof性能測試
- GORM
- 入門教程
- 模型定義
- 數據庫連接
- 插入數據
- 查詢數據
- 更新數據
- 刪除數據
- 事務處理
- 關聯查詢
- 屬于 (BELONG TO)
- 一對一 (Has One)
- 一對多 (Has Many)
- 多對多 (Many to Many)
- 預加載 (Preloading)
- 錯誤處理
- 第三方常用插件
- viper 讀取配置文件
- zap 高性能日志
- Nginx代理配置
- Goland 快捷鍵