如何使函数能够处理不同类型的输入?

huangapple go评论90阅读模式
英文:

How to make function work with different input types?

问题

我有一个简单的通用请求结构体,用于在我的应用程序中进行GET请求:

package api

import (
    "net/http"
    "time"
    "log"
    "app/errors"
)

type Request struct {
    Url string
}

func (request *Request) Run(responseObject *AppStatusInfo) *errors.Error {

    req, requestErr := http.NewRequest(http.MethodGet, request.Url, nil)

    req.Header.Set("Content-Type", "application/json")

    timeout := time.Duration(5 * time.Second)

    client := &http.Client{
        Timeout: timeout,
    }

    resp, requestErr := client.Do(req)

    if requestErr != nil {
        return &errors.UnknownError
    }

    decodeError := DecodeJsonRequestBody(resp, &responseObject)

    if (decodeError != nil) {
        return &errors.UnknownError
    }

    defer resp.Body.Close()

    return nil
}

这里的responseObject是一个指向AppStatusInfo类型的指针,它是一个带有一些字段的结构体。

我像这样运行它,以获取应用程序状态信息并将其放入appStatusInfo对象中:

var appStatusInfo AppStatusInfo

req := Request{
    Url:config.Config.ApiUrl,
}

req.Run(&appStatusInfo)

所以,这段代码运行得很好。

但是,当我想要将Request泛化以接受其他类型的响应,比如UserProducts时,我不知道如何在不将responseObject *AppStatusInfo替换为responseObject interface{}的情况下实现,然后使用responseObject.(UserProducts)进行类型转换,我认为这可以改进。

因此,由于没有泛型,我该如何使Request.Run()接受不同类型并返回相应的对象呢?

英文:

I have this simple generic Request struct to make get requests in my app:

package api

import (
    "net/http"
    "time"
    "log"
    "app/errors"
)

type Request struct {
    Url string
}

func (request *Request) Run(responseObject *AppStatusInfo) *errors.Error {

    req, requestErr := http.NewRequest(http.MethodGet, request.Url, nil)

    req.Header.Set("Content-Type", "application/json")

    timeout := time.Duration(5 * time.Second)

    client := &http.Client{
        Timeout: timeout,
    }

    resp, requestErr := client.Do(req)

    if requestErr != nil {
        return &errors.UnknownError
    }

    decodeError := DecodeJsonRequestBody(resp, &responseObject)

    if (decodeError != nil) {
        return &errors.UnknownError
    }

    defer resp.Body.Close()

    return nil
}

Here responseObject has pointer of type AppStatusInfo which is a struct with some fields.

I run it like this to get app status information and put it inside appStatusInfo object:

var appStatusInfo AppStatusInfo

req := Request{
    Url:config.Config.ApiUrl,
}

req.Run(&appStatusInfo)

So, this code runs fine.

But, when I want to generalize Request to accept other types of responses, like UserProducts, I don't know how to do it without replacing responseObject *AppStatusInfo with responseObject interface{}, then casting it with responseObject.(UserProducts) which I think can be improved.

So, as soon as there are no generics, how do I make Request.Run() accept different types and return respective objects?

答案1

得分: 1

假设DecodeJsonRequestBody将第二个参数传递给json.Unmarshaljson.Decoder.Decode,那么可以按照以下方式进行修改。我只展示了更改的行:

func (request *Request) Run(responseObject interface{}) *errors.Error {
   ...
   resp, requestErr := client.Do(req)
   if requestErr != nil {
      return &errors.UnknownError
   }
   defer resp.Body.Close()   // 在执行其他操作之前延迟关闭
  ...
  decodeError := DecodeJsonRequestBody(resp, responseObject) // 不要取responseObject的地址
  ...
}

你可以这样调用它:

var up UserProducts
err = r.Run(&up)

var asi AppStatusInfo
err = r.Run(&asi)

不需要类型断言和类型转换。

英文:

Assuming that DecodeJsonRequestBody passes the second argument to json.Unmarshal or json.Decoder.Decode, then write it like this. I show the changed lines only:

func (request *Request) Run(responseObject interface{}) *errors.Error {
   ...
   resp, requestErr := client.Do(req)
   if requestErr != nil {
      return &errors.UnknownError
   }
   defer resp.Body.Close()   // defer close before doing anything else
  ...
  decodeError := DecodeJsonRequestBody(resp, responseObject) // don't take address of responseObject
  ...
}

You can call it like this:

var up UserProducts
err = r.Run(&up)

var asi AppStatusInfo
err = r.Run(&asi)

Type assertions and type conversions are not required.

huangapple
  • 本文由 发表于 2017年3月2日 14:10:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/42548027.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定