2017-03-02 76 views
0

我有這個簡單的通用要求結構使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) 

因此,該代碼運行正常。

但是,當我想概括請求中接受其他類型的響應,像UserProducts,我不知道該怎麼做,而不與responseObject interface{}更換responseObject *AppStatusInfo,然後用responseObject鑄造它。(UserProducts),我覺得可以改進。

因此,只要沒有泛型,我如何讓Request.Run()接受不同的類型並返回相應的對象?

+0

很確定空接口是你唯一的選擇。 –

回答

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() // defer close before doing anything else 
    ... 
    decodeError := DecodeJsonRequestBody(resp, responseObject) // don't take address of responseObject 
    ... 
} 

你可以這樣調用:

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

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

類型的斷言和類型轉換不是必需的。

相關問題