go并发获取数据

go语言可以很轻松的实现并发获取数据,就算是新手也可以按部就班的套用现成的并发模式来实现并发。以下是一个简单的测试程序,其中有串行,并行。

package main

import (
	"sync"
	"time"
	"fmt"
)
func main() {
	syncFunc()
	fmt.Println(">>>>>>>>>>>>>>>")
	asyncFunc()
	fmt.Println(">>>>>>>>>>>>>>>")
	asyncChanFunc()
}
// 串行执行
func syncFunc() {
	var n,m,x int
	start := time.Now()
	fmt.Println("syncFunc start:",start)
	func () {
		time.Sleep(time.Second*1)
		n = 1
	}()
	func () {
		time.Sleep(time.Second*2)
		m = 2
	}()
	func () {
		time.Sleep(time.Second*3)
		x  =3
	}()
	t := time.Now()
	fmt.Println(t)
	elapsed := t.Sub(start)
	fmt.Println("syncFunc end:", elapsed, n, m, x)
}
// 并行执行
func asyncFunc() {
	var n,m,x int
	var wg sync.WaitGroup
	wg.Add(3)
	start := time.Now()
	fmt.Println("asyncFunc start:", start)
	go func () {
		defer wg.Done()
		time.Sleep(time.Second*1)
		n = 1
	}()
	go func () {
		defer wg.Done()
		time.Sleep(time.Second*2)
		m = 2
	}()
	go func () {
		defer wg.Done()
		time.Sleep(time.Second*3)
		x = 3
	}()
	wg.Wait()
	t := time.Now()
	fmt.Println(t)
	elapsed := t.Sub(start)
	fmt.Println("asyncFunc end:", elapsed, n, m, x)
}

// 并行执行
func asyncChanFunc() {
	var n, m, x =make(chan int),make(chan int),make(chan int)
	start := time.Now()
	fmt.Println("asyncChanFunc start:",start)
	go func () {
		time.Sleep(time.Second*1)
		n <- 1
	}()
	go func () {
		time.Sleep(time.Second*2)
		m <- 2
	}()
	go func () {
		time.Sleep(time.Second*3)
		x <- 3
	}()

	fmt.Printf("n:%d, m:%d, x:%d\n",<-n, <-m, <-x)
	t := time.Now()
	fmt.Println(t)
	elapsed := t.Sub(start)
	fmt.Println("asyncChanFunc end:", elapsed)
}

测试结果:

测试结果

看完代码和执行结果再来详细说明一下,time.Sleep(time.Second*1)是用来模拟该段程序需要执行n秒,syncFunc函数是串行的,耗时6秒。asyncFuncasyncChanFunc是并行的。耗时近乎3秒。而这两种模式略有不同, ** asyncFunc使用了sync.WaitGroup**

Add添加了3个goroutine Done是每一个goroutine执行完减1 Wait是阻塞上面的代码,只有当WaitGroup中的goroutine数量为0才往下执行 这种模式算是很简单直观的实现了并行。

** asyncChanFunc则是使用了chanel来实现并发** 可以看到程序中有fmt.Printf("n:%d, m:%d, x:%d\n",<-n, <-m, <-x)这段代码,目的是用来阻塞程序,如果n, m, x中没有写入数据,<-n, <-m, <-x不能读取到数据就会一直阻塞。

如果没有线程间的数据通信的话使用asyncFunc即可,chanel适用于更复杂的场景。

完整项目:https://github.com/yuedun/metal