doushang2571 2018-07-25 21:45
浏览 44
已采纳

在Rest API中使用Goroutine-获取未定义的错误

I am learning GO and wanted to make a simple rest API.

What I want to do is fire off a goroutine after handling the api request and do the work asynchronously in the background.

Here's my implementation so far:

package main

import (
    "encoding/json"
    "log"
    "net/http"

    "github.com/julienschmidt/httprouter"
)

// APIResponse represents common structure of every api call response
type APIResponse struct {
    Status string `json:"status"`
    Error  string `json:"error,omitempty"`
    Data   string `json:"data,omitempty"`
}

// Action represents what could be passed to the goroutine
type Action = func()

// ActionQueue represents a buffered channel
type ActionQueue = chan Action

func main() {
    r := httprouter.New()
    r.GET("/test", test)

    var apiServerPort = ":80"
    err := http.ListenAndServe(apiServerPort, r)
    if err != nil {
        log.Fatal("ListenAndServe:", err)
    } else {
        log.Printf("Started server on port %s", apiServerPort)
    }

    var queueSize = 10
    queue := make(ActionQueue, queueSize)
    for i := 0; i < queueSize; i++ {
        go worker(queue)
    }
    log.Printf("Started %d queue workers", queueSize)
}

func test(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
    successResponse(w, http.StatusOK, "Hello World")
    queue <- func() {
        log.Println("Hello from queue worker, initiated by api call")
    }
}

func successResponse(w http.ResponseWriter, statusCode int, successData string) {
    sendResponse(w, statusCode, "", successData)
}

func errorResponse(w http.ResponseWriter, statusCode int, errorData string) {
    sendResponse(w, statusCode, errorData, "")
}

func sendResponse(w http.ResponseWriter, statusCode int, errorData string, responseData string) {
    w.WriteHeader(statusCode)
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(&APIResponse{Status: http.StatusText(statusCode), Error: errorData, Data: responseData})
}

func worker(queue ActionQueue) {
    for action := range queue {
        action()
    }
}

When I try to run this code, I am getting the following error (on this line queue <- func() { ... }):

./main.go:46:2: undefined: queue

How can I make the queue channel available to my request handler (i.e. httprouter GET request handler func)?

Secondly, I cannot see the output from my log.Printf() calls in the console output (stdout), e.g. server status message when the app runs. Any ideas why?

  • 写回答

1条回答 默认 最新

  • dongyu8694 2018-07-25 22:28
    关注

    Couple of things are wrong, first your main function is not ordered correctly, you want to initialize you channel and start workers before you run err := http.ListenAndServe(apiServerPort, r) so something like this

    func main() {
        var queueSize = 10
        queue := make(ActionQueue, queueSize)
        for i := 0; i < queueSize; i++ {
            go worker(queue)
        }
        log.Printf("Started %d queue workers", queueSize)
    
        // routers and stuff...
    }
    

    Then queue variable is not defined in the test() function, which is why you are getting ./main.go:46:2: undefined: queue. You could fix it with a higher order function e.g.

    func test(queue ActionQueue) httprouter.Handle {
        return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
            successResponse(w, http.StatusOK, "Hello World")
            queue <- func() {
                log.Println("Hello from queue worker, initiated by api call")
            }
        }
    }
    

    and then just bind it to the route with r.GET("/test", test(queue))

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?