Golang处理程序处理不同类型

dro*_*ime 2 dry go

这些是AppHandler,来自我在网上找到的模式,同时研究大猩猩/多路复用器.它们是满足http.Handler的结构的一部分.如果您注意到,以下两个块完全相同.实际上,它们可以作为字符串传递"变体"("流程"或"过程").

func CreateFlow(a *AppContext, w http.ResponseWriter, r *http.Request) (int, error) {

    highest, code, err := a.Create("flow", r)
    if code != 200 || err != nil {
        return code, err
    }

    b := new(bytes.Buffer)
    json.NewEncoder(b).Encode(struct {
        Highest int `json:"id"`
    }{highest})
    w.Header().Set("Content-Type", "application/json")
    w.Write(b.Bytes())
    return 200, nil
}

func CreateProcess(a *AppContext, w http.ResponseWriter, r *http.Request) (int, error) {

    highest, code, err := a.Create("process", r)
    if code != 200 || err != nil {
        return code, err
    }

    b := new(bytes.Buffer)
    json.NewEncoder(b).Encode(struct {
        Highest int `json:"id"`
    }{highest})
    w.Header().Set("Content-Type", "application/json")
    w.Write(b.Bytes())
    return 200, nil
}
Run Code Online (Sandbox Code Playgroud)

但是,以下两个块不仅需要字符串,而且还需要相关类型的变量("Flow"和"Process")才能成功解组我从ElasticSearch获得的命中.除此之外,它们是相同的代码.

func GetFlow(a *AppContext, w http.ResponseWriter, r *http.Request) (int, error) {

    hit, code, err := a.GetByID("flow", mux.Vars(r)["id"], r)
    if code != 200 {
        return code, err
    }

    var flow Flow

    err = json.Unmarshal(*hit.Source, &flow)
    if err != nil {
        return 500, err
    }

    flow.ESID = hit.Id

    b := new(bytes.Buffer)
    json.NewEncoder(b).Encode(flow)
    w.Header().Set("Content-Type", "application/json")
    w.Write(b.Bytes())
    return 200, nil
}

func GetProcess(a *AppContext, w http.ResponseWriter, r *http.Request) (int, error) {

    hit, code, err := a.GetByID("process", mux.Vars(r)["id"], r)
    if code != 200 {
        return code, err
    }

    var process Process

    err = json.Unmarshal(*hit.Source, &process)
    if err != nil {
        return 500, err
    }

    process.ESID = hit.Id

    b := new(bytes.Buffer)
    json.NewEncoder(b).Encode(process)
    w.Header().Set("Content-Type", "application/json")
    w.Write(b.Bytes())
    return 200, nil
}
Run Code Online (Sandbox Code Playgroud)

当涉及声明的类型时,我不确定如何在golang中推广这种行为.这些处理程序也在同一个包中,因为我认为它们都在完成类似的任务.我在代码中非常清楚地重复自己,但我需要有关如何改进的建议.我已经过去了"一点复制比一点依赖更好." 但我害怕因为"反思永远不会清楚".

以下是使用其中一个函数的main声明示例.

api.Handle("/flow/{id:[0-9]+}", handlers.AppHandler{context, handlers.GetFlow}).Methods("GET")
Run Code Online (Sandbox Code Playgroud)

Adr*_*ian 6

您可以通过传递必要类型的示例来执行此操作,方法与此相同Unmarshal:

func GetFlow(a *AppContext, w http.ResponseWriter, r *http.Request) (int, error) {
    return GetThing(a,w,r,"flow",new(Flow))
}

func GetProcess(a *AppContext, w http.ResponseWriter, r *http.Request) (int, error) {
    return GetThing(a,w,r,"process",new(Process))
}

func GetThing(a *AppContext, w http.ResponseWriter, r *http.Request, t string, ob Elastible{}) (int, error) {
    hit, code, err := a.GetByID(t, mux.Vars(r)["id"], r)
    if code != 200 {
        return code, err
    }

    err = json.Unmarshal(*hit.Source, ob)
    if err != nil {
        return 500, err
    }

    ob.SetESID(hit.Id)

    b := new(bytes.Buffer)
    json.NewEncoder(b).Encode(ob)
    w.Header().Set("Content-Type", "application/json")
    w.Write(b.Bytes())
    return 200, nil
}

type Elastible interface {
    SetESID(id ESIDType)    // whatever type ESID is, not clear from example
}

func (f *Flow) SetESID(id ESIDType) {
    f.ESID = id
}
Run Code Online (Sandbox Code Playgroud)

这段代码是未经测试的(因为我没有你的struct defs或其他相关代码),但我希望它可以得到这个想法.