Go语言八股之并发详解

06-01 1674阅读

   💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

Go语言八股之并发详解

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

 

前言

小郑最近在准备Go语言的面试题,通过github和b站等各种学习网站上学习go语言的八股文,并且整理出自己觉得面试可能会问到的知识点,希望通过做笔记的方式来巩固自己的知识点,并且也希望可以帮助到大家在面试的时候更加得心应手一些,那么从现在开始,和我一起加入八股学习之旅吧!

1.Go 中主协程如何等待其余协程退出?

答:Go 的 sync.WaitGroup 是等待一组协程结束,sync.WaitGroup 只有 3 个方法,Add()是添加计数,Done()减去一个计数,Wait()阻塞直到所有的任务完成。Go 里面还能通过有缓冲的 channel 实现其阻塞等待一组协程结束,这个不能保证一组 goroutine 按照顺序执行,可以并发执行协程。Go 里面能通过无缓冲的 channel 实现其阻塞等待一组协程结束,这个能保证一组 goroutine 按照顺序执行,但是不能并发执行。

Add(n int):设置需要等待的协程数量。通常在启动协程之前调用,传入一个整数,表示需要等待的协程数量。

Done():每个协程完成时调用,通常在协程的最后,减少等待的计数。

Wait():主协程通过调用 Wait() 来阻塞,直到计数器减少到零,表示所有协程都完成。

2.多个 goroutine 对同一个 map 写会 panic,异常是否可以用 defer 捕获?

可以捕获异常,但是只能捕获一次,Go语言,可以使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别的情况下,才使用Go中引入的Exception处理:defer, panic, recover Go中,对异常处理的原则是:多用error包,少用panic

3.golang实现多并发请求(发送多个get请求)

在go语言中其实有两种方法进行协程之间的通信。一个是共享内存、一个是消息传递

共享内存(互斥锁)

//基本的GET请求
package main
 
import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
    "sync"
    "runtime"
)
 
// 计数器
var counter int = 0
 
func httpget(lock *sync.Mutex){
    lock.Lock()
    counter++
    resp, err := http.Get("http://localhost:8000/rest/api/user")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
    fmt.Println(resp.StatusCode)
    if resp.StatusCode == 200 {
        fmt.Println("ok")
    }
    lock.Unlock()
}
 
func main() {
    start := time.Now()
    lock := &sync.Mutex{}
    for i := 0; i = 800 {
            break
        }
    }
    end := time.Now()
    consume := end.Sub(start).Seconds()
    fmt.Println("程序执行耗时(s):", consume)
}

问题

我们可以看到共享内存的方式是可以做到并发,但是我们需要利用共享变量来进行协程的通信,也就需要使用互斥锁来确保数据安全性,导致代码啰嗦,复杂话,不易维护。我们后续使用go的消息传递方式避免这些问题。

消息传递(管道)

//基本的GET请求
package main
 
import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)
// HTTP get请求
func httpget(ch chan int){
    resp, err := http.Get("http://localhost:8000/rest/api/user")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
    fmt.Println(resp.StatusCode)
    if resp.StatusCode == 200 {
        fmt.Println("ok")
    }
    ch 
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码