首頁 > 後端開發 > Golang > 主體

有沒有辦法約束(通用)類型參數?

王林
發布: 2024-02-09 13:18:19
轉載
423 人瀏覽過

有沒有辦法約束(通用)類型參數?

php小編柚子探討了一個常見問題:有沒有辦法約束(通用)類型參數?在PHP中,我們經常需要對函數或方法的參數進行類型約束,以確保傳入的參數符合特定的類型要求。然而,對於通用類型參數,如數組或對象,目前還沒有直接的約束方式。但是,我們可以透過編寫更嚴格的類型檢查邏輯來實現對通用類型參數的約束,以確保參數的正確性和一致性。在本文中,我們將探討幾種實現通用類型參數限制的方法,以及它們的優缺點。

問題內容

我剛開始學習泛型。因此,我嘗試為在某些 protobuf 訊息上運行的自訂資料庫通用一個驅動程式。

我想找到一種方法來進一步約束我的泛型類型,但作為指針,即確保(告訴編譯器)約束 e 實現了另一種方法。

首先,我限制了資料庫可以處理的實體。

type entity interface {
   pb.msga | pb.msgb | pb.msgc
}
登入後複製

然後,編寫了一個描述資料庫功能的通用接口,以便處理各自的原始訊息的不同服務可以使用它:

type db[e entity] interface {
   get(...) (e, error)
   list(...) ([]e, error)
   ...
}
登入後複製

到目前為止一切順利。但是,我還希望在與資料庫通訊時對這些實體進行(反)序列化,以便透過網路發送、克隆和合併。像這樣的事情:

func encode[e entity](v *e) ([]byte, error) {
   return proto.marshal(v)
}
登入後複製

但是,上面的程式碼給了以下錯誤:

cannot use val (variable of type *e) as type protoreflect.protomessage in argument to proto.marshal: *e does not implement protoreflect.protomessage (type *e is pointer to type parameter, not type parameter)
登入後複製

問題是proto.marshal 需要實體(*e)來實現proto.message 接口,即protoreflect() 方法,我所有的實體類型都實作了該方法,但它不受約束,編譯器無法推斷。

我還嘗試將實體定義為:

type Entity interface {
   *pb.MsgA | *pb.MsgB | *pb.MsgC
   proto.Message
}
登入後複製

但是,除了我需要執行一些額外的 protreflect 操作來實例化實體指標所引用的 proto.messages 之外,這感覺不太對。

解決方法

你可以這樣做:

func encode[m interface { *e; proto.message }, e entity](v m) ([]byte, error) {
    return proto.marshal(v)
}
登入後複製

如果您想要比上面更簡潔的語法,您可以取消訊息約束:

type Message[E Entity] interface {
    *E
    proto.Message
}

func Encode[M Message[E], E Entity](v M) ([]byte, error) {
    return proto.Marshal(v)
}
登入後複製

https://www.php.cn/link/20ba66f905957b34253d9d7abde919f3

以上是有沒有辦法約束(通用)類型參數?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!