我很难将变量从主程序包传递到另一个程序包。
我要做什么:
我有一个简单的http守护程序,该守护程序可以接收传入的POST请求,并将其推送到RabbitMQ实例,该消息将由某些工作程序处理。由于消息可能很大,因此我尝试实现一个简单的资源管理器。它应该接受或拒绝请求。
它是这样的:
package main
import (
"flag"
"fmt"
"github.com/couchbaselabs/logg"
"net/http"
_ "net/http/pprof"
)
var resourceChannel = make(chan bool)
var ampqApiConfig = worker.DefaultResManagerConfig()
var ServiceCanAccept bool
func main() {
var http_port int
flagFunc := func() {
flag.IntVar(
&http_port,
"http_port",
8080,
"The http port to listen on, eg, 8081",
)
}
rabbitConfig := worker.DefaultConfigFlagsOverride(flagFunc)
// any requests to root, just redirect to main page
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
text := `<h1>We are running!<h1>`
fmt.Fprintf(w, text)
})
http.Handle("/req", worker.NewHttpHandler(rabbitConfig))
http.Handle("/status", worker.NewHttpStatusHandler())
listenAddr := fmt.Sprintf(":%d", http_port)
logg.LogTo("HTTP", "Starting listener on %v", listenAddr)
// start a goroutine which will decide if we have resources for future requests
go func() {
for {
resourceChannel <- worker.AcceptRequest(&qApiConfig)
ServiceCanAccept = <-resourceChannel
worker.ServiceCanAccept = ServiceCanAccept
time.Sleep(10 * time.Second)
}
}()
logg.LogError(http.ListenAndServe(listenAddr, nil))
}
我在通道和全局变量上方定义。然后,我尝试每10秒运行一次布尔函数(AcceptRequest),并将变量传递给软件包“ worker”中的woker.ServiceCanAccept变量。但不幸的是,它不起作用。 goroutine仅执行一次(至少我只看到一次来自资源管理器的日志),并且目标包中worker.ServiceCanAccept的值不变。这是第一个问题。
对于每个请求,将调用http.Handle("/req", worker.NewHttpHandler(rabbitConfig))
,并执行下面的ServeHTTP。但是var ServiceCanAccept bool
永远不会改变。我是否需要创建一个与包main中相同名称的通道,并从中读取值?
package worker
import (
"encoding/json"
"fmt"
"github.com/couchbaselabs/logg"
"net/http"
)
type HttpHandler struct {
RabbitConfig RabbitConfig
}
func NewHttpHandler(r RabbitConfig) *HttpHandler {
return &HttpHandler{
RabbitConfig: r,
}
}
var ServiceCanAccept bool
func (s *HttpHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
logg.LogTo("HTTP", "serveHttp called")
defer req.Body.Close()
Request := Request{}
decoder := json.NewDecoder(req.Body)
err := decoder.Decode(&Request)
if err != nil {
logg.LogError(err)
http.Error(w, "Unable to unmarshal json", 500)
return
}
Result, err := HandleRequest(Request, s.RabbitConfig)
if err != nil {
msg := "Unable to perform decode. Error: %v"
errMsg := fmt.Sprintf(msg, err)
logg.LogError(fmt.Errorf(errMsg))
http.Error(w, errMsg, 500)
return
}
w.Header().Set("Content-Type", "application/json")
js, err := json.Marshal(Result)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(js)
}
func HandleRequest(Request Request, rabbitConfig RabbitConfig) (Result, error) {
defaultResManagerConfig := DefaultResManagerConfig()
if !ServiceCanAccept {
err := fmt.Errorf("no ressources available to proced the request")
return Result{}, err
}
switch Request.InplaceDecode {
case true:
Engine := NewEngine(Request.EngineType)
Result, err := Engine.ProcessRequest(Request)
if err != nil {
msg := "Error processing request. Error: %v"
errMsg := fmt.Sprintf(msg, err)
logg.LogError(fmt.Errorf(errMsg))
return Result{}, err
}
return Result, nil
default:
Client, err := NewRpcClient(rabbitConfig)
if err != nil {
logg.LogError(err)
return Result{}, err
}
Result, err := Client.DecodeImage(Request)
if err != nil {
logg.LogError(err)
return Result{}, err
}
return Result, nil
}
}
谢谢!