2018-03-17 21:48 阅读 46


I've been reading a few go blogs and and more recently I stubbled upon Peter Bourgon's talk titled "Ways to do things". He shows a few examples of the actor pattern for concurrency in GO. Here is a handler example using such pattern:

func (a *API) handleNext(w http.ResponseWriter, r *http.Request) {
    var (
        notFound   = make(chan struct{})
        otherError = make(chan error)
        nextID     = make(chan string)
    a.action <- func() {
        s, err := a.log.Oldest()
        if err == ErrNoSegmentsAvailable {
        if err != nil {
            otherError <- err
        id := uuid.New()
        a.pending[id] = pendingSegment{s, time.Now().Add(a.timeout), false}
        nextID <- id
    select {
    case <-notFound:
        http.NotFound(w, r)
    case err := <-otherError:
        http.Error(w, err.Error(), http.StatusInternalServerError)
    case id := <-nextID:
        fmt.Fprint(w, id)

And there's a loop behind the scenes listening for the action channel:

func (a *API) loop() {
    for {
        select {
        case f := <-a.action:

My question is what is the benefit to all of this? The handler isn't any faster because it is still blocking until some action in the action func returns something to it. Which is essentially the same thing as just returning the function from outside the go routine. What am I missing here?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • 已采纳
    douyao5533 douyao5533 2018-03-17 22:04

    The benefits are not to a single call but to the sum of all calls.

    For example you can use this to limit actual execution to a single goroutine and thereby avoid all the problems concurrent execution would bring with it.

    For example I use this pattern to synchronise all usage of a connection to a hardware device that talks serial.

    点赞 评论 复制链接分享