Go語言并發(fā)范式之future模式詳解
1、Go語言并發(fā)范式-future模式
編程中經(jīng)常遇到在一個流程中需要調(diào)用多個子調(diào)用的情況,這些子調(diào)用相互之間沒有依賴,如果串行地調(diào)用,則耗時會很長,此時可以使用Go并發(fā)編程中的future模式。
future模式的基本工作原理:
(1)、使用chan作為函數(shù)參數(shù)。
(2)、啟動goroutine調(diào)用函數(shù)。
(3)、通過chan傳入?yún)?shù)。
(4)、做其他可以并行處理的事情。
(5)、通過chan異步獲取結(jié)果。
package main
import (
"fmt"
"time"
)
// 一個查詢結(jié)構(gòu)體
// 這里的sql和result是一個簡單的抽象,具體的應用,可能是更復雜的數(shù)據(jù)類型
type query struct {
//參數(shù)Channel
sql chan string
//結(jié)果Channel
result chan string
}
//執(zhí)行Query
func execQuery(q query) {
//啟動協(xié)程
go func() {
//獲取輸入
sql := <-q.sql
//訪問數(shù)據(jù)庫
//輸出結(jié)果通道
q.result <- "result from " + sql
}()
}
func main() {
//初始化Query
q := query{make(chan string, 1), make(chan string, 1)}
//執(zhí)行Query,注意執(zhí)行的時候無需準備參數(shù)
go execQuery(q)
//準備參數(shù)
q.sql <- "select * from table;"
//do otherthings
time.Sleep(1 * time.Second)
//獲取結(jié)果
fmt.Println(<-q.result)
}程序輸出
result from select * from table;
future最大的好處是將函數(shù)的同步調(diào)用轉(zhuǎn)換為異步調(diào)用,適用于一個交易需要多個子調(diào)用且這些子調(diào)用沒有依賴
的場景。實際情況可能比上面示例復雜得多,要考慮錯誤和異常的處理,讀者著重體驗這種思想,而不是細節(jié)。
2、Future模式的實現(xiàn)步驟
(1)、構(gòu)建結(jié)構(gòu)體FutureTask
這里我們將要做的事情抽象成任務,對于每個任務我們可能需要傳遞參數(shù)過去,并且我們還需要得到這個任務的執(zhí)行結(jié)果,為此,我們創(chuàng)建兩個channel,一個用于傳遞參數(shù),一個用于保存結(jié)果。(具體還需要什么其他的參數(shù)可以根據(jù)具體業(yè)務進行設(shè)計)。
// FutureTask 在并發(fā)執(zhí)行時用于傳遞參數(shù)和保存返回的結(jié)果
type FutureTask struct {
// 用于傳遞參數(shù)
args chan interface{}
// 實際業(yè)務中可能還有很多其他的數(shù)據(jù)
// 用于保存結(jié)果
res chan interface{}
}(2)、創(chuàng)建goroutine執(zhí)行future的方法
在創(chuàng)建好FutureTask之后,需要開啟goroutine去執(zhí)行,為此需要創(chuàng)建一個執(zhí)行FutureTask的方法:
// execFutureTask 用于開啟一個Future模式的線程
func execFutureTask(futureTask *FutureTask) {
// 讀取傳入的參數(shù)
fmt.Println("goroutine讀取到的參數(shù):", <-futureTask.args)
// 這里可以執(zhí)行具體的業(yè)務邏輯
result := "執(zhí)行完業(yè)務邏輯后得到的結(jié)果"
// 將結(jié)果進行保存
futureTask.res <- result
defer close(futureTask.res)
return
}(3)、測試代碼
package main
import (
"fmt"
"time"
)
// FutureTask 在并發(fā)執(zhí)行時用于傳遞參數(shù)和保存返回的結(jié)果
type FutureTask struct {
// 用于傳遞參數(shù)
args chan interface{}
// 實際業(yè)務中可能還有很多其他的數(shù)據(jù)
// 用于保存結(jié)果
res chan interface{}
}
// execFutureTask 用于開啟一個Future模式的線程
func execFutureTask(futureTask *FutureTask) {
// 讀取傳入的參數(shù)
fmt.Println("goroutine讀取到的參數(shù):", <-futureTask.args)
// 這里可以執(zhí)行具體的業(yè)務邏輯
result := "執(zhí)行完業(yè)務邏輯后得到的結(jié)果"
// 將結(jié)果進行保存
futureTask.res <- result
defer close(futureTask.res)
return
}
func main() {
// 創(chuàng)建一個FutureTask并開啟一個goroutine去執(zhí)行
futureTask := FutureTask{make(chan interface{}), make(chan interface{})}
go execFutureTask(&futureTask)
// 向FutureTask傳入?yún)?shù),如果不傳的話會死鎖
futureTask.args <- "main線程傳入的參數(shù)"
// 這里可以并行的去執(zhí)行一些其他業(yè)務邏輯
time.Sleep(1 * time.Second)
// 讀取線程執(zhí)行的
fmt.Println("主線程讀取future模式下goroutine的結(jié)果:", <-futureTask.res)
}(4)、執(zhí)行結(jié)果
程序輸出
goroutine讀取到的參數(shù): main線程傳入的參數(shù)
主線程讀取future模式下goroutine的結(jié)果: 執(zhí)行完業(yè)務邏輯后得到的結(jié)果
(5)、完整代碼
package main
import (
"fmt"
"time"
)
// FutureTask 在并發(fā)執(zhí)行時用于傳遞參數(shù)和保存返回的結(jié)果
type FutureTask struct {
// 用于傳遞參數(shù)
args chan interface{}
// 實際業(yè)務中可能還有很多其他的數(shù)據(jù)
// 用于保存結(jié)果
res chan interface{}
}
// execFutureTask 用于開啟一個Future模式的線程
func execFutureTask(futureTask *FutureTask) {
// 讀取傳入的參數(shù)
fmt.Println("goroutine讀取到的參數(shù):", <-futureTask.args)
// 這里可以執(zhí)行具體的業(yè)務邏輯
result := "執(zhí)行完業(yè)務邏輯后得到的結(jié)果"
// 將結(jié)果進行保存
futureTask.res <- result
defer close(futureTask.res)
return
}
func main() {
// 創(chuàng)建一個FutureTask并開啟一個goroutine去執(zhí)行
futureTask := FutureTask{make(chan interface{}), make(chan interface{})}
go execFutureTask(&futureTask)
// 向FutureTask傳入?yún)?shù),如果不傳的話會死鎖
futureTask.args <- "main線程傳入的參數(shù)"
// 這里可以并行的去執(zhí)行一些其他業(yè)務邏輯
time.Sleep(1 * time.Second)
// 讀取線程執(zhí)行的
fmt.Println("主線程讀取future模式下goroutine的結(jié)果:", <-futureTask.res)
}到此這篇關(guān)于Go語言并發(fā)范式之future模式詳解的文章就介紹到這了,更多相關(guān)Go future模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
axios?gin的GET和POST請求實現(xiàn)示例
這篇文章主要為大家介紹了axios?gin的GET和POST請求實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04
完美解決go Fscanf 在讀取文件時出現(xiàn)的問題
這篇文章主要介紹了完美解決go Fscanf 在讀取文件時出現(xiàn)的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
Golang Gin框架實現(xiàn)文件下載功能的示例代碼
本文主要介紹了Golang Gin框架實現(xiàn)文件下載功能的示例代碼,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12

