假設我寫了兩個這樣的函式:
func ToInterfaceSlice[T any](s []T) []interface{} {
res := make([]interface{}, len(s))
for i, v := range s {
res[i] = v
}
return res
}
func FromInterfaceSlice[T any](s []interface{}) (res []T, err error) {
res = make([]T, len(s))
for i, v := range s {
vt, ok := v.(T)
if !ok {
return nil, fmt.Errorf("%v (type=%T) doesn't fit the target type %T", v, v, res)
}
res[i] = vt
}
return
}
當我從輸入引數決議型別時,我可以簡單地使用
var m = []int{1, 2, 3}
fmt.Println(ToInterfaceSlice(m))
編譯器知道Tis int。
但是,當我嘗試從回傳變數傳遞型別時
var m []int
m, _ = FromInterfaceSlice([]interface{}{1, 2, 3})
fmt.Println(m)
編譯器給出錯誤:
.\scratch.go:29:27: 無法推斷 T
我必須在函式呼叫中顯式傳遞型別:
var m []int
m, _ = FromInterfaceSlice[int]([]interface{}{1, 2, 3})
fmt.Println(m)
當接收者變數不是介面時,有什么難以從回傳型別推斷型別引數的嗎?或者只是沒有實施,甚至沒有故意實施?
評論后更新#1
我知道a, b := GenericFunc()不能參考回傳值的型別。目前 Go 確實有“取決于”情況,是否需要來自用戶輸入的顯式實體化。
type Set[T comparable] map[T]struct{}
func NewSet[T comparable](eles ...T) Set[T] {
s := make(Set[T])
for _, ele := range eles {
s[ele] = struct{}{}
}
return s
}
可以同時使用t := NewSet(1, 2, 3)and t := NewSet[string](),但var t NewSet[float64] = NewSet()現在不行,因為這個
uj5u.com熱心網友回復:
當前的型別推斷規則是明確的。未考慮如何使用回傳值:
型別推斷基于
- 型別引數串列
- 使用已知型別引數初始化的替換映射 M(如果有)
- 普通函式引數的(可能為空)串列(僅在函式呼叫的情況下)
從 Go 1.18 開始,可能會簡單地重寫你的函式以接受所需型別的引數;這還有一個好處是不在函式體內隱藏分配:
func FromInterfaceSlice[T any](s []interface{}, dst []T) error {
if len(s) != len(dst) {
return errors.New("lengths don't match")
}
for i, v := range s {
vt, ok := v.(T)
if !ok {
return nil, fmt.Errorf("%v (type=%T) doesn't fit the target type %T", v, v, res)
}
dst[i] = vt
}
return nil
}
并傳入具有所需長度的目標切片:
func main() {
src := []interface{}{1, 2, 3}
m := make([]int, len(src))
_ = FromInterfaceSlice(src, m)
fmt.Println(m)
}
如果您不能或不想事先確定切片的長度,則只能進行顯式實體化。
此外,型別引數仍然不能通過:=簡寫宣告來推斷:
// what is m???
m, err := FromInterfaceSlice([]interface{}{1, 2, 3})
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/474120.html
