英文:
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.DB
和p *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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论