【问题标题】:Using goroutines and channels in a http handler在 http 处理程序中使用 goroutine 和通道
【发布时间】:2013-03-27 01:10:42
【问题描述】:

我已经实现了一个非常简单的 twitter 客户端阅读器:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "time"
)

type twitterResult struct {
    Results []struct {
        Text     string `json:"text"`
        Ids      string `json:"id_str"`
        Name     string `json:"from_user_name"`
        Username string `json:"from_user"`
        UserId   string `json:"from_user_id_str"`
    }
}

var (
  twitterUrl = "http://search.twitter.com/search.json?q=%23UCL"
  pauseDuration = 5 * time.Second
)

func retrieveTweets(c chan<- *twitterResult) {
    for {
        resp, err := http.Get(twitterUrl)
        if err != nil {
            log.Fatal(err)
        }

        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body)
        r := new(twitterResult) //or &twitterResult{} which returns *twitterResult
        err = json.Unmarshal(body, &r)
        if err != nil {
            log.Fatal(err)
        }
        c <- r
        time.Sleep(pauseDuration)
    }

}

func displayTweets(c chan *twitterResult) {
    tweets := <-c
    for _, v := range tweets.Results {
        fmt.Printf("%v:%v\n", v.Username, v.Text)
    }

}

func main() {
    c := make(chan *twitterResult)
    go retrieveTweets(c)
    for {
        displayTweets(c)
    }

}

我现在想为它构建一个简单的 Web 客户端并让它显示 twitter 结果。但我对在 http 处理程序中调用 goroutines 持谨慎态度。有人指出我正确的方向吗?

【问题讨论】:

  • 搜索关键字在每个请求中是静态的还是变化的?

标签: http go channels


【解决方案1】:

您在 HTTP 请求的上下文中使用 goroutine 有点受限,因为该 HTTP 请求需要响应,而不是“等到稍后”。这里有几个选项:

  1. 使用网络套接字。我从来没有在 Go 中实现过 websocket,所以我在那里没有任何经验,但这确实是让客户端等待数据并在数据进入时显示它的最佳方式。This blog post 似乎有一个很好的教程。 (您也可以在这里使用 COMET 框架来实现类似的功能。)

  2. 不要使用 goroutines,而是使用 AJAX 请求来保持客户端的异步性(完全是一个词)。这看起来像客户端加载您的页面,它向您的服务器发出一堆 AJAX 请求,您可以在多个线程中处理这些请求,因此理论上它们可以在同一时间完成。请注意,您可以生成一个 goroutine 来响应特定请求,但应该期望该 goroutine 完全响应该请求。

  3. 使用 goroutine 向 Twitter API 发出所有请求,但要等待它们全部完成并将它们集中在一起,然后再完成请求并做出响应。这可以让您的所有 Twitter API 请求同时发生并节省您在后端的时间,但您的客户端仍然必须等待那个时间(最慢的 API 请求)才能向用户显示任何内容。

如果是我并且我很匆忙,我会选择选项 2,将繁重的工作留给客户端,而只使用服务器作为 Twitter API 的代理。但选项 1 会是更好的解决方案,尤其是如果您不太担心浏览器兼容性。

【讨论】:

  • websocket 思路不错;你也可以用 EventSource 做类似的事情。我将 websockets 用于来自我的 DNS 服务器的“实时”使用数据 - websocket 的代码位于 github.com/abh/geodns/blob/master/monitor.go
猜你喜欢
  • 1970-01-01
  • 2017-08-16
  • 2011-03-04
  • 2014-11-01
  • 2015-08-31
  • 2015-02-27
  • 2013-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多