空接口是绕过类型系统的一种方式吗?

我正在学习Go(来自Python),强制打字系统实际上很有帮助。我对的了解非常有限,导致我使用以下代码,其中我从API检索JSON数据并返回解析版本。结果可以是对象或对象列表。interface{}


func getJsonFromApi(endpoint string) (reply interface{}, err error) {

    res, err := http.Get("http://127.0.0.42/api/" + endpoint)

    if err != nil {

        return nil, err

    }

    body, err := ioutil.ReadAll(res.Body)

    err = res.Body.Close()

    if err != nil {

        return nil, err

    }

    err = json.Unmarshal(body, &reply)

    return reply, nil

}

它有效,但我通过颠覆类型系统感到不舒服。这是 的预期用法吗?interface{}


我最终会将代码更改为始终返回一个对象数组(并在我的第一个用例中获取第一个对象),但我对一般问题感到好奇。


慕妹3242003
浏览 98回答 2
2回答

慕莱坞森

如果可能,最好使用 .您可以使用 :structmappackage mainimport (   "encoding/json"   "net/http")func main() {   r, e := http.Get("https://github.com/manifest.json")   if e != nil {      panic(e)   }   defer r.Body.Close()   m := make(map[string]interface{})   json.NewDecoder(r.Body).Decode(&m)   s := m["icons"].([]interface{})[0].(map[string]interface{})["sizes"].(string)   println(s == "114x114")}但是正如你所看到的,当你需要解开包装以获得实际价值时,它会变得非常痛苦。 好多了:structpackage mainimport (   "encoding/json"   "net/http")func main() {   r, e := http.Get("https://github.com/manifest.json")   if e != nil {      panic(e)   }   defer r.Body.Close()   var m struct {      Icons []struct { Sizes string }   }   json.NewDecoder(r.Body).Decode(&m)   s := m.Icons[0].Sizes   println(s == "114x114")}

慕标5832272

空接口 是指定零个方法的接口。它可以保存任何类型的值(https://tour.golang.org/methods/14),因此它是您在不知道实际类型的情况下用来保存某些内容的类型。interface{}在像您这样的示例中,有时这是必要的,但代价是强类型化。我不认为你应该在你的例子中使用它感到不舒服,但是如果它最终到处都是,你应该开始感到不舒服。您可以允许方法的调用方传入实际类型,如果您改用此签名:func getJsonFromApi(endpoint string, reply interface{}) (err error) {我会说它是类型系统的一部分,而不是绕过它的方法。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go