在RESTAPI中使用goroutine-出现未定义错误

在RESTAPI中使用goroutine-出现未定义错误,go,goroutine,httprouter,Go,Goroutine,Httprouter,我正在学习GO,希望制作一个简单的RESTAPI 我想做的是在处理api请求后启动一个goroutine,并在后台异步完成工作 以下是我目前的实施情况: package main import ( "encoding/json" "log" "net/http" "github.com/julienschmidt/httprouter" ) // APIResponse represents common structure of every api cal

我正在学习GO,希望制作一个简单的RESTAPI

我想做的是在处理api请求后启动一个goroutine,并在后台异步完成工作

以下是我目前的实施情况:

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()
    }
}
主程序包
进口(
“编码/json”
“日志”
“net/http”
“github.com/julienschmidt/httprouter”
)
//APIResponse表示每个api调用响应的公共结构
类型APIResponse结构{
状态字符串`json:“状态”`
错误字符串`json:“错误,省略为空”`
数据字符串`json:“数据,省略为空”`
}
//动作表示可以传递给goroutine的内容
类型Action=func()
//ActionQueue表示缓冲通道
类型ActionQueue=chan Action
func main(){
r:=httprouter.New()
r、 获取(“/test”,test)
var apiServerPort=“:80”
错误:=http.listendServe(apiServerPort,r)
如果错误!=零{
log.Fatal(“ListendServe:,错误)
}否则{
log.Printf(“已在端口%s上启动服务器”,apiServerPort)
}
var queueSize=10
队列:=生成(ActionQueue,queueSize)
对于i:=0;iqueue有两件事是错误的,首先您的主函数顺序不正确,您希望在运行
err:=http.listenandservice(apiServerPort,r)
之前初始化通道并启动工作程序

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...
}

然后用
r.GET(“/test”,test(queue))

将队列通道设为全局通道(不推荐),将其绑定到路由,或者将处理程序定义为结构,并使队列成为结构的一个字段,或者使用闭包。
http.ListenAndServe
阻塞,直到出现服务器错误,因此所有代码都是空闲的,并且只有在http.ListenAndServe返回后才会执行,因此log.Printf不会执行。@mkopriva这是有意义的。因此,如果我nt要进行简单的调试输出,最好的方法是什么?将队列代码移到http.ListenAndServe上方。@mkopriva我已经尝试过了,但仍然没有从
log.Printf()调用的stdout中获得任何内容
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")
        }
    }
}