如何避免在 Go 中重复自己?
How to avoid repeating myself in Go?
我刚开始接触 Go,我的背景包括 泛型。由于 Go still 不支持泛型,我想知道如何让我的代码保持干燥?
看看下面的例子,request
参数有一个动态类型,returns 一个动态响应(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{})
您可以使用与 json.Unmarshal
和其他 decoders/unmarshalers 接受类型 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
}
我刚开始接触 Go,我的背景包括 泛型。由于 Go still 不支持泛型,我想知道如何让我的代码保持干燥?
看看下面的例子,request
参数有一个动态类型,returns 一个动态响应(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{})
您可以使用与 json.Unmarshal
和其他 decoders/unmarshalers 接受类型 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
}