go - 只为接口(interface)传递方法参数一次?

标签 go

我正在尝试找出一种方法来使我的代码更短更简单,方法是仅在父结构(?)中调用一次接口(interface)方法的参数

首先是路由定义:

func Init() {
    // Create route
    r := mux.NewRouter()

    // Default routes
    router.Route("/", webtest.TestController{}, r)

    // Serve the routes
    router.Serve(r)
}

然后是它的功能:

type Controller struct {
    ControllerInterface
}

type ControllerInterface interface {
    Get(w http.ResponseWriter, r *http.Request)
}

func Route(path string, ct interface{}, r *mux.Router) {
    if c, ok := ct.(controllers.ControllerInterface); ok {
        r.HandleFunc(path, http.HandlerFunc(c.Get)).Methods("GET")
    }
}

然后我调用路由

type TestController struct {
    controllers.Controller
}

func (c TestController) Get(w http.ResponseWriter, r *http.Request) {
    println("Hello World")
}

如您所见,我必须在所有地方都使用 w http.ResponseWriter, r *http.Request,否则路由将无法正常工作。有什么办法可以将这些参数包含在父结构(或类似结构)中,这样我就不必每次都包含它了吗?

最佳答案

很遗憾,我认为不会有您满意的答案。归根结底,以下必须为真:

每个处理程序必须使用 http.Responsewriter*http.Request 来为请求提供服务。

要记住的一点是,更短和更简单并不总是齐头并进。将作者和响应传递给需要它们的函数,虽然有点冗长,但非常简单。

可能让您最高兴的是将大部分逻辑实际上向下推到一些处理操作语义而不是网络请求层的附加方法中。以使用 GET 请求加载记录为例,您可以将其结构化为:

func main() {
    http.DefaultServeMux.HandleFunc("/", getHandler)

    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

func getHandler(w http.ResponseWriter, r *http.Request) {
    // Do stuff with the request, like deserialize
    // Extract the ID
    // Call getLogic
    // return an appropriate error or serialize the response back out
}

func getLogic(recordID int) (Record, error) {
    // Do actual interesting logic here.
}

像这样拆分它并非没有潜在的简单性成本。虽然它确实让您无需处理 http.ResponseWriterhttp.Request 即可测试您的逻辑 block ,但您现在必须决定在何处切断该接缝。持续这样做可能会很尴尬。

您也可以尝试采用不同的方法,例如为每个请求创建一个结构,将编写器和请求放在上面,然后调用适当的方法,但我不推荐这样做:

func getHandler(w http.ResponseWriter, r *http.Request) {
    SingleRequest{w, r}.Get()
}

type SingleRequest struct {
    writer  http.ResponseWriter
    request *http.Request
}

func (s SingleRequest) Get() {
    // Do logic here, but the method still has to access s.writer and s.request
}

这两种方法都没有提供太多的简洁性。在我看来,它们确实产生的少量简洁是以简单为代价的。然而,第一种方法可能是合理的,具体取决于给定处理程序的复杂性。它毕竟是小函数分解大函数模式的延伸。

就目前而言,我不知道有任何方法可以在降低代码大小的同时普遍提高简单性。相反,我们应该关注为什么您觉得这是一个需要首先解决的问题。你熟悉httptest吗?标准库中的包?如果您关心测试,它将帮助您测试这些处理程序。

关于go - 只为接口(interface)传递方法参数一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50774964/

相关文章:

go - 获取错误未定义 : math in go lang when using math/rand library

bash - makefile 中的 make 规则始终成功

arrays - 将 int[] 传递给函数但函数返回空数组

go - 在 Golang 和 ncurses 中只接受字母数字

go - 当函数具有接收器参数时,如何制作函数映射?

json - 在 Go 语言中解析 JSON : Attribute without name

go - 未定义 : revel. 测试套件

go - 在 kafka-go 中读取具有特定 ID 的消息

go - Golang将slice append 到slice的slice上,那么slice会一直影响slice的slice吗?

import - golang 远程导入失败