Как избежать повторения в Go? - PullRequest
0 голосов
/ 13 апреля 2020

Я только начал с Go, и мой фон включает в себя generics . Поскольку Go все еще не поддерживает генерики, мне интересно, как мне сохранить мой код DRY?

Посмотрите на приведенный ниже пример, аргумент request имеет тип Dynami c, который возвращает динамический ответ c (PaymentMethodResponse). Если я хочу создать другой запрос, я копирую и вставляю весь код внутри метода, меняя только тип request и response и переменную localVarPath.

/*
PaymentMethods Returns available payment methods.
Queries the available payment methods for a transaction based on the transaction context (like amount, country, and currency). Besides giving back a list of the available payment methods, the response also returns which input details you need to collect from the shopper (to be submitted to `/payments`).  Although we highly recommend using this endpoint to ensure you are always offering the most up-to-date list of payment methods, its usage is optional. You can, for example, also cache the `/paymentMethods` response and update it once a week.
 * @param request PaymentMethodsRequest - reference of PaymentMethodsRequest).
 * @param ctxs ..._context.Context - optional, for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
@return PaymentMethodsResponse
*/

func (a *Checkout) PaymentMethods(request *PaymentMethodsRequest, ctxs ..._context.Context) (PaymentMethodsResponse, *_nethttp.Response, error) {
    var (
        localVarHTTPMethod  = _nethttp.MethodPost
        localVarPostBody    interface{}
        localVarReturnValue PaymentMethodsResponse
    )

    // create path and map variables
    localVarPath := a.BasePath() + "/paymentMethods"
    localVarHeaderParams := make(map[string]string)
    localVarQueryParams := _neturl.Values{}

    // to determine the Content-Type header
    localVarHTTPContentTypes := []string{"application/json"}

    // set Content-Type header
    localVarHTTPContentType := common.SelectHeaderContentType(localVarHTTPContentTypes)
    if localVarHTTPContentType != "" {
        localVarHeaderParams["Content-Type"] = localVarHTTPContentType
    }

    // to determine the Accept header
    localVarHTTPHeaderAccepts := []string{"application/json"}

    // set Accept header
    localVarHTTPHeaderAccept := common.SelectHeaderAccept(localVarHTTPHeaderAccepts)
    if localVarHTTPHeaderAccept != "" {
        localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
    }
    // body params
    if request != nil {
        localVarPostBody = request
    }

    var ctx _context.Context
    if len(ctxs) == 1 {
        ctx = ctxs[0]
    }

    r, err := a.Client.PrepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams)
    if err != nil {
        return localVarReturnValue, nil, err
    }

    localVarHTTPResponse, err := a.Client.CallAPI(r)
    if err != nil || localVarHTTPResponse == nil {
        return localVarReturnValue, localVarHTTPResponse, err
    }

    localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body)
    localVarHTTPResponse.Body.Close()
    if err != nil {
        return localVarReturnValue, localVarHTTPResponse, err
    }

    if localVarHTTPResponse.StatusCode >= 300 {
        newErr := common.NewAPIError(localVarBody, localVarHTTPResponse.Status)
        return localVarReturnValue, localVarHTTPResponse, newErr
    }

    err = a.Client.Decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
    if err != nil {
        newErr := common.NewAPIError(localVarBody, err.Error())
        return localVarReturnValue, localVarHTTPResponse, newErr
    }

    return localVarReturnValue, localVarHTTPResponse, nil
}

Пример использование: (запрос является json структурой)

res, httpRes, err := client.Checkout.PaymentMethods(&checkout.PaymentMethodsRequest{})

1 Ответ

2 голосов
/ 13 апреля 2020

Вы можете использовать тот же подход, который используется json.Unmarshal и другими декодерами / демаршалерами, которые принимают аргумент типа interface{} и вместо возврата значения неизвестного типа они сохраняют результат своей операции в предоставляется interface{} аргумент.

Вот пример псевдокода:

func apicall(req, res interface{}) error {
    inputbody, err := jsonencode(req)
    if err != nil {
        return err
    }

    response, err := httpclient.postrequest(inputbody)
    if err != nil {
        return err
    }

    return jsondecode(res, response.body)
}

func main() {
    req := new(PaymentMethodsRequest)
    res := new(PaymentMethodsResponse)
    if err := apicall(req, res); err != nil {
        return err
    }

    // do something with res
}
...