Go解决方案,用于删除重复代码(延迟,net / http)

I have a below code in Go:

func (api *ApiResource) create(request *restful.Request, response *restful.Response) {
    account := &DefaultAccount
    err := request.ReadEntity(account)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return
    }
    tmpl := data_transformer.ParseTemplate("xml/accAdd.xml")
    payload := data_transformer.RenderTemplate(tmpl, account)
    resp, err := http.Post(url, "application/xml", payload)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return
    }

    // Body closes when either at the end of the function or at return
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)

    aResp := new(AResp)
    err = xml.Unmarshal(body, aResp)
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }
    response.WriteHeader(http.StatusCreated)
    response.WriteEntity(aResp)
}

func (api *ApiResource) updateLimit(request *restful.Request, response *restful.Response) {
    account := &DefaultLimit
    err := request.ReadEntity(account)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return
    }
    tmpl := data_transformer.ParseTemplate("xml/addLimit.xml")
    payload := data_transformer.RenderTemplate(tmpl, account)
    resp, err := http.Post(url, "application/xml", payload)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return
    }

    // Body closes when either at the end of the function or at return
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)

    aResp := new(AResp)
    err = xml.Unmarshal(body, aResp)
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }
    response.WriteHeader(http.StatusCreated)
    response.WriteEntity(aResp)
}

I want to be able to remove duplicate codes in an elegant way Go style.

If I do remove them and put them in separate function, would all defer and net/http package work as expected for different calls and xml file loads?

What is a good Go type solutions for this?

You can separate almost the whole function and just pass to it the "account" and the xml file to read.

Also it's a better practice to use xml.Decoder instead of xml.Unmarshal when reading from streams.

func updateEntity(response *restful.Response, fn string, iface interface{}) {
    tmpl := data_transformer.ParseTemplate("xml/" + fn)
    payload := data_transformer.RenderTemplate(tmpl, iface)
    resp, err := http.Post(url, "application/xml", payload)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return
    }

    defer resp.Body.Close()
    dec := xml.NewDecoder(resp.Body)
    body, err := ioutil.ReadAll(resp.Body)

    aResp := &AResp{}
    err = dec.Decode(aResp)
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }
    response.WriteHeader(http.StatusCreated)
    response.WriteEntity(aResp)
}

func (*ApiResource) create(request *restful.Request, response *restful.Response) {
    account := &DefaultAccount
    err := request.ReadEntity(account)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return
    }
    updateEntity(response, "accAdd.xml", account)
}
func (*ApiResource) updateLimit(request *restful.Request, response *restful.Response) {
    account := &DefaultLimit
    err := request.ReadEntity(account)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return
    }
    updateEntity(response, "addLimit.xml", account)
}