Go   发布时间:2022-04-09  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了在 Golang 中使用 Go 关键字和 Channel 实现并行大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

Go 关键字和 chAnnel 的用法

go 关键字用来创建 goroutIne (协程),是实现并发的关键。go 关键字的用法如下:
//go 关键字放在方法调用前新建一个 goroutIne 并让他执行方法体
go GetThingDone(param1,param2);

//上例的变种,新建一个匿名方法并执行
go func(param1,param2) {
}(val1,val2)

//直接新建一个 goroutIne 并在 goroutIne 中执行代码块
go {
    //do someTing...
}
因为 goroutIne 在多核 cpu 环境下是并行的。如果代码块在多个 goroutIne 中执行,我们就实现了代码并行。那么问题来了,怎么拿到并行的结果呢?这就得用 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 中获取执行结果。

一个很 low 的并行示例

fmt.Println(time.Now())
resultChan1 := UnblockGet("http://127.0.0.1/test.PHP?i=1")
resultChan2 := UnblockGet("http://127.0.0.1/test.PHP?i=2")

fmt.Println(<-resultChan1)
fmt.Println(<-resultChan1)
fmt.Println(time.Now())

上面两个 http 请求是在两个 goroutIne 中并行的。总的执行时间小于 两个请求时间和。

这个例子只是为了体现 go 和 chAnnel 的用法,有内存泄漏问题,千万不要在线上这么搞。因为新建的 chAnnel 没有 close。下次写一个更高级一点的。

简单的实现 http multi GET

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)
}

大佬总结

以上是大佬教程为你收集整理的在 Golang 中使用 Go 关键字和 Channel 实现并行全部内容,希望文章能够帮你解决在 Golang 中使用 Go 关键字和 Channel 实现并行所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。