并发编程最佳实践作业疑问

并发编程最佳实践作业疑问

问题描述:

1、lock := make(chan content) 需要加buffer吗?试了一下不加程序也不会挂掉,加了是不是可以防止channel阻塞?

2、go fetch(name, lock) 协程里面执行http请求,如果http请求超时,会不会导致 c := <-lock 代码处阻塞?

​3、下图代码还有没有其它问题?

相关代码:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

type content struct {
    name string
    url  string
    body []byte
}

func main() {
    urls := []string{
        "baidu.com",
        "bing.com",
    }

    lock := make(chan content)
    for _, name := range urls {
        go fetch(name, lock)
    }
    c := <-lock
    writeToFile(c.name, c.url, c.body)
}

func fetch(name string, lock chan content) {
    url := fmt.Sprintf("https://%s", name)
    resp, err := http.Get(url)
    if err != nil {
        panic("request failed")
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        panic("Failed to read buffer data")
    }

    content := content{
        name: name,
        url:  url,
        body: body,
    }
    lock <- content
}

func writeToFile(name, url string, body []byte) {
    if err := ioutil.WriteFile("./"+name+".html", body, 0644); err != nil {
        panic("Failed to write to file")
    }
}

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

按生产标准来写的话,你这里超时就会导致 goroutine 泄露~


生产环境向外发请求一定要加超时,不要直接用 http.Get 这种 API

  • qq_Tto_0 提问者 #1

    明白了,谢谢曹大,我又改了一版

    1
    package main<br><br>import (<br>   "fmt"<br>   "io/ioutil"<br>   "log"<br>   "net/http"<br>   "time"<br>)<br><br>type Handle struct {<br>   client *http.Client<br>   lock   chan content<br>}<br><br>func NewClient() *Handle {<br>   client := &http.Client{<br>      Timeout: 30 * time.Second,<br>   }<br>   lock := make(chan content)<br>   return &Handle{client, lock}<br>}<br><br>type content struct {<br>   name string<br>   url  string<br>   body []byte<br>}<br><br>func main() {<br>   n := NewClient()<br>   urls := []string{<br>      "baidu.com",<br>      "bing.com",<br>   }<br><br>   for _, name := range urls {<br>      go n.fetch(name)<br>   }<br>   c := <-n.lock;<br>   n.writeToFile(c.name, c.url, c.body)<br>}<br><br>func (n *Handle) fetch(name string) {<br>   url := fmt.Sprintf("https://%s", name)<br>   req, _ := http.NewRequest(http.MethodGet, url, nil)<br>   resp, err := n.client.Do(req)<br>   if err != nil {<br>      fmt.Printf("request error, err:%s", err)<br>      return<br>   }<br>   defer resp.Body.Close()<br>   if resp.StatusCode != http.StatusOK {<br>      fmt.Printf("response err status code: %d,url: %s\n", resp.StatusCode, req.URL)<br>      return<br>   }<br><br>   body, err := ioutil.ReadAll(resp.Body)<br>   if err != nil {<br>      log.Fatalf("Failed to read buffer data, err:%s", err)<br>   }<br><br>   content := content{<br>      name: name,<br>      url:  url,<br>      body: body,<br>   }<br>   n.lock <- content<br>}<br><br>func (n *Handle) writeToFile(name, url string, body []byte) {<br>   if err := ioutil.WriteFile("./"+name+".html", body, 0644); err != nil {<br>      fmt.Printf("Failed to write to file, err:%s\n", err)<br>   }<br>}<br>


    2021-07-07 19:58:48
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师
插入代码