background
The requirement for the current business scenario is to request both dynamic and static data in the form of concurrency, that is, doing both things together, to reduce time consuming. But at the end of the day you need to process both dynamic and static data separately and then aggregate it into a single result and send it back upstream. Golang is said to be built for high concurrency, and this time it uses some of golang’s features.
Knowledge points involved
- sync.WaitGroup{}
- channel
One of two ways
- Use only WaitGroup{}, using two data structures to record the return of two coroutines
- Use WaitGroup{} and use a channel to complete the communication using a single data structure to process the return
Only WaitGroup
// +build ignore
package main
import (
"fmt"
"sync"
)
/* @func: Test the use of waitGroup @time: 2021/11/29 @author: Andy_ Wendo */
func main(a) {
var wg sync.WaitGroup
wg.Add(2)
staticData := make(map[string]interface{})
dynamicData := make(map[string]interface{})
static(staticData, &wg)
dynamic(dynamicData, &wg)
wg.Wait()
fmt.Println("static and dynamic done")
fmt.Println("staticData->", staticData)
fmt.Println("dynamicData->", dynamicData)
}
// Static data acquisition
func static(staticData map[string]interface{}, wg *sync.WaitGroup) {
defer wg.Done()
staticData["static"] = "data"
staticData["index"] = 1
}
// Dynamic data acquisition
func dynamic(dynamicData map[string]interface{}, wg *sync.WaitGroup) {
defer wg.Done()
dynamicData["dynamic"] = "data"
dynamicData["index"] = 0
}
Copy the code
Output result:
WaitGroup And Channel
Func getAllData(uid, source, from, logId, kind String, richSel []string, logBuf * logrus.entry) (string, logBuf * logrus.entry) error) { var wg sync.WaitGroup var result []byte resultChannel := make(chan map[string]interface{}, 2) defer close(resultChannel) resultMap := make(map[string]interface{}) testMap := make(map[string]interface{}) Go func() {var flag int = 0 for response := range resultChannel {flag++ for k, v := range response { resultMap[k] = v fmt.Printf("%v-> %v\n", k, v) } if flag >= 2 { break } } outMap := make(map[string]interface{}) outMap["data"] = resultMap outMap["err_code"] = 0 outMap["err_msg"] = "ok" result, _ = json.Marshal(outMap) wg.Done() }() go getWaitStatic(uid, source, from, logId, kind, resultChannel, logBuf, &wg) go getWaitDynamic(uid, logId, kind, richSel, resultChannel, logBuf, &wg) wg.Wait() fmt.Println("test->", testMap) return string(result), nil }Copy the code
That is, a coroutine is opened to obtain data twice, and data is passed between dynamic data and static data. When a channel obtains data twice, it encapsulates the returned data.
conclusion
Both methods can be used to share data, and more uses (including controlling timeouts, etc.) are still to be implemented