亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

將接口與 golang 中的類型聯合

將接口與 golang 中的類型聯合

Go
萬千封印 2022-12-13 16:24:48
我正在嘗試在 Golang 中實現一些緩存功能,但我希望它們對字符串和實現該接口的其他對象都有效Stringer。我正在嘗試使用 Golang 泛型,這是我目前所擁有的:import (    "fmt")type String interface {    ~string | fmt.Stringer}然而,這給出了一個錯誤cannot use fmt.Stringer in union (fmt.Stringer contains methods)。有沒有辦法在不依賴反射或類型裝箱/拆箱的情況下做到這一點?
查看完整描述

2 回答

?
吃雞游戲

TA貢獻1829條經驗 獲得超7個贊

混淆可能是有道理的,因為類型參數提案建議像你的代碼,但最終成為 Go 1.18 中的實現限制。

它在specs和 Go 1.18 發行說明中提到。規格是規范參考:

實現限制:一個聯合(多于一個術語)不能包含預先聲明的標識符comparable或指定方法的接口,或嵌入comparable或指定方法的接口。

對于為什么這沒有包含在 Go 1.18 版本中,也有一些廣泛的解釋。tl;dr 簡化了聯合類型集的計算(盡管在 Go 1.18 中,類型參數的方法集也不是隱式計算的......)。

還要考慮,無論有沒有這個限制,除了傳遞給使用反射的函數之外,您可能不會獲得任何有用的東西T。要調用方法,~string | fmt.Stringer您仍然必須進行類型斷言或類型切換。

請注意,如果這種約束的目的只是為了打印字符串值,您可以只使用fmt.Sprint,它使用反射。

string對于更廣泛的情況,當參數可以采用(without ~) 和 等確切類型時,如 colm.anseo's answer 中的類型斷言或開關工作得很好fmt.Stringer。對于近似值,~string 您無法窮盡地處理所有可能的項,因為這些類型集實際上是無限的。所以你又回到了反思。更好的實現可能是:

func StringLike(v any) string {

    // switch exact types first

    switch s := v.(type) {

    case fmt.Stringer:

        return s.String()


    case string:

        return s

    }


    // handle the remaining type set of ~string

    if r := reflect.ValueOf(v); r.Kind() == reflect.String {

        return r.String()

    }


    panic("invalid type")

}

游樂場:https://go.dev/play/p/-wzo2KPKzWZ


查看完整回答
反對 回復 2022-12-13
?
森欄

TA貢獻1810條經驗 獲得超5個贊

泛型——理論上允許使用多種類型——在編譯時選擇單一的具體類型。接口允許在運行時使用多種類型。您希望同時將這兩者結合起來——不幸的是,這是不可能的。


在不使用反射的情況下,最接近的方法是使用運行時類型斷言:


func StringLike(v any) string {


    if s, ok := v.(string); ok {

        return s

    }


    if s, ok := v.(fmt.Stringer); ok {

        return s.String()

    }


    panic("non string invalid type")

}

https://go.dev/play/p/p4QHuT6R8yO


查看完整回答
反對 回復 2022-12-13
  • 2 回答
  • 0 關注
  • 131 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號