zoukankan      html  css  js  c++  java
  • Go关键字和Channel实现并行

    go关键字是实现并发的关键

    go关键字用来创建goroutine(携程), 是实现并发的关键。go关键字用法如下

    // go关键字放在方法调用前新建一个 goroutine  让他执行方法体
    go GetResult(param1, param2);
    
    //上例的变种,新建一个匿名方法并执行
    go func(param1, param2){
    }(val, val2)
    
    // 直接新建一个goroutine   并在goroutine 中执行代码块
    go {
      //do something
    }
    

    使用channel拿到并行的结果

    //resultChan 是一个 int 类型的 channel。类似一个信封,里面放的是 int 类型的值。
    var resultChan chan int
    //将 123 放到这个信封里面,供别人从信封中取用
    resultChan <- 123
    //从 resultChan 中取值。这个时候 result := 123
    result := <- resultChan
    

    使用go关键字和channel实现非阻塞调用

    阻塞的意思是调用方在被调用的代码返回之前必须一直等待,不能处理别的事情。而非阻塞调用则不用等待,调用之后立刻返回。那么返回值如何获取呢?Node.js 使用的是回调的方式,Golang 使用的是 channel。

    /**
     * 每次调用方法会新建一个 channel : resultChan,
     * 同时新建一个 goroutine 来发起 http 请求并获取结果。
     * 获取到结果之后 goroutine 会将结果写入到 resultChan。
     */
    func UnblockGet(requestUrl string) chan string {
        resultChan := make(chan string)
        go func() {
            request := httplib.Get(requestUrl)
            content, err := request.String()
            if err != nil {
                content = "" + err.Error()
            }
            resultChan <- content
        } ()
        return resultChan
    }
    

    由于新建的 goroutine 不会阻塞函数主流程的执行,所以调用 UnblockGet 方法会立刻得到一个 resultChan 返回值。一旦 goroutine 执行完毕拿到结果就会写入到 resultChan 中,这时外部就可以从 resultChan 中获取执行结果。

    示例方法

    type RemoteResult struct {
        Url string
        Result string
    }
    
    func RemoteGet(requestUrl string, resultChan chan RemoteResult)  {
        request := httplib.NewBeegoRequest(requestUrl, "GET")
        request.SetTimeout(2 * time.Second, 5 * time.Second)
        //request.String()
        content, err := request.String()
        if err != nil {
            content = "" + err.Error()
        }
        resultChan <- RemoteResult{Url:requestUrl, Result:content}
    }
    func MultiGet(urls []string) []RemoteResult {
        fmt.Println(time.Now())
        resultChan := make(chan RemoteResult, len(urls))
        defer close(resultChan)
        var result []RemoteResult
        //fmt.Println(result)
        for _, url := range urls {
            go RemoteGet(url, resultChan)
        }
        for i:= 0; i < len(urls); i++ {
            res := <-resultChan
            result = append(result, res)
        }
        fmt.Println(time.Now())
        return result
    }
    
    func main() {
        urls := []string{
            "http://127.0.0.1/test.php?i=13",
            "http://127.0.0.1/test.php?i=14",
            "http://127.0.0.1/test.php?i=15",
            "http://127.0.0.1/test.php?i=16",
            "http://127.0.0.1/test.php?i=17",
            "http://127.0.0.1/test.php?i=18",
            "http://127.0.0.1/test.php?i=19",
            "http://127.0.0.1/test.php?i=20"    }
        content := MultiGet(urls)
        fmt.Println(content)
    }
    

    示例方法二

    func main(){
    	// 创建一个无缓存的channel 数据类型为字符串
    	c := make(chan string)
    	//声明一个数组
    	endList := [5]string{"first", "second", "third", "forty", "fifteen"}  
    	for _,v := range endList{
    		// 用a接受v的值
    		go func(a string)  {    	
    			time.Sleep(5 * time.Second)
    			c <- a
    			fmt.Println("add success")
    		//把v作为参数传入到协程中
    		}(v)           						
    	}
    
    	// 主进程一直监听处理channel, 当channel处理长度符合要求时,跳出循环语句
    	var count int
    	for data := range c{
    		fmt.Println(data)
    		count += 1
    		if count == len(endList){
    			break
    		}
    	}
    }
    

    参考文档

    思否文章

  • 相关阅读:
    ubuntu 启动 重启 停止 apache
    /usr/bin/env: php: No such file or directory 【xunsearch demo项目体验】【已解决】
    安装mezzanine时报:storing debug log for failure【已解决】
    redhat 安装 setuptools【成功】
    SnowNLP:一个处理中文文本的 Python 类库[转]
    Android 了解1G 2G 3G 知识
    Android-体系架构
    Android-bindService远程服务(Aidl)-初步
    Android-SDCard外部存储文件读写
    Android-文件模式
  • 原文地址:https://www.cnblogs.com/ppwang06/p/go_channel.html
Copyright © 2011-2022 走看看