在`http.HandlerFunc`中添加多个参数。

huangapple go评论72阅读模式
英文:

add multiple params in http.HandlerFunc

问题

你好,我正在尝试为一个使用"net/http"和"net/http/httptest"的POST请求编写单元测试。如果在我的处理程序中除了w http.ResponseWriter和r *http.Request之外还有其他参数,比如db、kafka等,我该怎么做呢?

如果我有一个如下的处理程序:

func ResponseHandler(w http.ResponseWriter, r *http.Request, db *dynamo.DB, p *Confluent.Producer)

你有什么想法如何处理呢?

我得到了以下错误信息:

*无法将ResponseHandler(类型为func(http.ResponseWriter,http.Request,dynamo.DB,"github.com/confluentinc/confluent-kafka-go/kafka"。Producer))转换为类型http.HandlerFunc

英文:

hi i am trying tr write unit test for a post request using

"net/http"
"net/http/httptest"

if in my handler i have extra parameter other than w http.ResponseWriter, r *http.Request like db , kafka, etc

func ResponseHandler(w http.ResponseWriter, r *http.Request, db *dynamo.DB, p *Confluent.Producer)

how can i do

handler := http.HandlerFunc(handlername) any idea ?

I m getting
***cannot convert ResponseHandler (type func(http.ResponseWriter, http.Request, dynamo.DB, "github.com/confluentinc/confluent-kafka-go/kafka".Producer)) to type http.HandlerFunc

答案1

得分: 4

您的处理程序需要实现http.Handler签名,这意味着它不能有其他参数或返回值。

提供其他参数的方法是使它们来自外部作用域。假设您的不真正是Handler的函数如下所示:

func ResponseHandler(w http.ResponseWriter, r *http.Request, db *dynamo.DB, p *Confluent.Producer)

...您需要生成一个实际的Handler来调用您的不真正是Handler的函数。假设您已经在路由器初始化函数中获取了DB和Producer,您可以这样路由:

var db *dynamo.DB = someDBFactory()
var p *Confluent.Producer = giveMeAProducer()

responseHandler := func(w http.ResponseWriter, r *http.Request) {
    return ResponseHandler(w, r, db, p)
})

http.HandleFunc(somePath, responseHandler)

您还可以通过使用高阶函数显式传递参数,而不是依赖于外部作用域:

var db *dynamo.DB := someDBFactory()
var p *Confluent.Producer := giveMeAProducer()

newResponseHandler := func(db *dynamo.DB, p *Confluent.Producer) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        return ResponseHandler(w, r, db, p)
    })
})

http.HandleFunc(somePath, newResponseHandler(db, p))
英文:

Your handler needs to implement the http.Handler signature, meaning it cannot have other arguments or return anything.

The way to provide it with other arguments is to have them come from an outer scope. So, assuming your not-really-a-Handler looks like:

func ResponseHandler(w http.ResponseWriter, r *http.Request, db *dynamo.DB, p *Confluent.Producer)

...you will need to generate an actual Handler calling your not-really-a-Handler. Supposing you already obtained the DB and Producer in your router initialization function, you can route like this:

var db *dynamo.DB = someDBFactory()
var p *Confluent.Producer = giveMeAProducer()

responseHandler := func(w http.ResponseWriter, r *http.Request) {
    return ResponseHandler(w, r, db, p)
})

http.HandleFunc(somePath, responseHandler)

You could also pass the parameters explicitly instead of relying on the outer scope, using a higher-order function:

var db *dynamo.DB := someDBFactory()
var p *Confluent.Producer := giveMeAProducer()

newResponseHandler := func(db *dynamo.DB, p *Confluent.Producer) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        return ResponseHandler(w, r, db, p)
    })
})

http.HandleFunc(somePath, newResponseHandler(db, p))

答案2

得分: 1

将HandlerFunc与您的自定义函数包装起来,如下所示:

func ResponseHandler(w http.ResponseWriter, r *http.Request, db *dynamo.DB, p *Confluent.Producer) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		// 在这里编写您的代码
	}
}

这段代码将返回一个函数,该函数接受http.ResponseWriter*http.Request作为参数,并在其中编写您的代码。

英文:

Wrap the HandlerFunc with your custom function as

func ResponseHandler(w http.ResponseWriter, r *http.Request, db *dynamo.DB, p *Confluent.Producer)func(http.ResponseWriter, *http.Request){
return func(http.ResponseWriter, *http.Request){
	// your code goes here
}}

答案3

得分: 1

我可能错了,但是这两个“额外”的参数(db *dynamo.DBp *Confluent.Producer)似乎与请求无关。如果处理程序依赖于它们来处理请求,你可以通过几种方式将这些依赖项提供给处理程序。有经验的 Gophers 倾向于通过方法接收器来“注入”依赖项。

你可以声明一个自定义的结构类型,其字段是处理程序所需的依赖项:

type API struct {
    db *dynamo.DB
    p  *Confluent.Producer
}

你可以去掉这两个额外的参数,并将你的 ResponseHandler 函数转换为自定义 API 类型的方法,从而使其与 http.HandlerFunc 类型兼容:

func (api *API) ResponseHandler(w http.ResponseWriter, r *http.Request) {
    // ...
}

最后,在 main 函数中,你只需要将依赖项连接到一个 API 变量中即可。

英文:

I may wrong, but the two "extra" parameters (db *dynamo.DB and p *Confluent.Producer) don't seem request-specific. If the handler depends on them to handle requests, you could make those dependencies available to the handler in several ways. Seasoned Gophers tend to "inject" dependencies through a method receiver.

You could declare a custom struct type whose fields are the dependencies needed by your handler(s):

type API struct {
    db *dynamo.DB
    p  *Confluent.Producer
}

You can drop the extra two parameters and turn your ResponseHandler function into a method on your custom API type, thereby making it compatible with the http.HandlerFunc type:

func (api *API) ResponseHandler(w http.ResponseWriter, r *http.Request) {
    // ...
}

Finally, you only have to wire the dependencies in an API variable in main.

huangapple
  • 本文由 发表于 2021年6月25日 18:41:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/68129661.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定