我正在嘗試撰寫以下函式:
func Fill[X any](slice []*X){
for i := range slice {
slice[i] = new(X)
}
}
xs := make([]*int, 10) // fill with nils
Fill(xs) // now fill with new(int)
這很好,但是……如果我想使用一部分介面并提供具體型別?
func Fill[X, Y any](slice []X){
for i := range slice {
slice[i] = new(Y) // not work!
}
}
xs := make([]sync.Locker, 10) // fill with nils
Fill[sync.Locker,sync.Mutex](xs) // ouch
我嘗試了一些組合都沒有成功,有沒有辦法或者go1.18不支持這種關系?
uj5u.com熱心網友回復:
當您同時約束X和Y時any,您將失去所有介面-實作者關系。在編譯時唯一知道的是X和Y是不同的型別,您不能在函式體內將一個分配給另一個。
使其編譯的一種方法是使用顯式斷言:
func Fill[X, Y any](slice []X) {
for i := range slice {
slice[i] = any(*new(Y)).(X)
}
}
但是,如果Y沒有真正實作X,就像您的情況一樣,這會引起恐慌,因為它是*sync.Mutex(指標型別)實作了sync.Locker.
此外,當Y用指標型別實體化時,您會丟失有關基本型別的資訊,因此會丟失零值,包括will *new(Y)be nil,因此您實際上并沒有基線改進make(只是型別化的 nil 與 nil 介面)。
您想要做的是約束Y到X, 就像Fill[X any, Y X](slice []X)但這是不可能的,因為 1) 型別引數不能用作約束;和/或 2) 約束不能直接嵌入型別引數。它還像上面一樣初始化 nils。
更好的解決方案是使用建構式而不是第二個型別引數:
func main() {
xs := make([]sync.Locker, 10)
Fill(xs, func() sync.Locker { return &sync.Mutex{} })
}
func Fill[X any](slice []X, f func() X) {
for i := range slice {
slice[i] = f()
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/447716.html
上一篇:出現錯誤“dialtcpxxx:xxx:xxx:xxx:3306:connect:connectiondenied”的情況是什么以及如何避免此錯誤
