2 回答

TA貢獻(xiàn)1946條經(jīng)驗(yàn) 獲得超4個(gè)贊
順便說一句,已經(jīng)有一個(gè)用于排序的庫
https://pkg.go.dev/golang.org/x/exp/slices#Sort
1. 您可以使用泛型創(chuàng)建接口,然后為其鍵入斷言。
例子:
type Lesser[T SupportedType] interface {
Less(T) bool
}
type Vec[T SupportedType] []T
func (vec Vec[T]) Less(a, b int) bool {
return any(vec[a]).(Lesser[T]).Less(vec[b])
}
func main() {
vs := Vec[String]([]String{"a", "b", "c", "d", "e"})
vb := Vec[Bool]([]Bool{false, true})
fmt.Println(vs.Less(3, 1))
fmt.Println(vb.Less(0, 1))
}
2.可以保存Vec上的類型。
例子:
type Lesser[T SupportedType] interface {
Less(T) bool
}
type Vec[T SupportedType, L Lesser[T]] []T
func (vec Vec[T, L]) Less(a, b int) bool {
return any(vec[a]).(L).Less(vec[b])
}
func main() {
vs := Vec[String, String]([]String{"a", "b", "c", "d", "e"})
fmt.Println(vs.Less(3, 1))
}
3.嵌套類型約束
謝謝@blackgreen
例子 :
type SupportedType interface {
Int8 | Time | Bool | String
}
type Lesser[T SupportedType] interface {
Less(T) bool
}
type Vec[T interface {
SupportedType
Lesser[T]
}] []T
func (vec Vec[T]) Less(a, b int) bool {
return vec[a].Less(vec[b])
}
func main() {
vs := Vec[String]([]String{"a", "b", "c", "d", "e"})
fmt.Println(vs.Less(3, 1))
}
基準(zhǔn):
benchmark 1 : 28093368 36.52 ns/op 16 B/op 1 allocs/op
benchmark 2 : 164784321 7.231 ns/op 0 B/op 0 allocs/op
benchmark 3 : 212480662 5.733 ns/op 0 B/op 0 allocs/op
Embedding a container inside type specific structs:
benchmark 4 : 211429621 5.720 ns/op 0 B/op 0 allocs/op
哪一個(gè)最適合您取決于您。但 IMO 3 號(hào)是最好的。

TA貢獻(xiàn)2051條經(jīng)驗(yàn) 獲得超10個(gè)贊
就我個(gè)人而言,我認(rèn)為最好不要在聯(lián)合中包含許多彼此無關(guān)的類型,因?yàn)樗鼈儾粫?huì)共享許多通用操作,并且您最終會(huì)編寫特定于類型的代碼。那么使用泛型的意義何在……?
無論如何,可能的策略取決于SupportedType約束類型集中包含的內(nèi)容,以及您希望對(duì)這些內(nèi)容執(zhí)行的操作:
只有確切的類型,沒有方法
使用類型開關(guān)T并運(yùn)行任何對(duì)具體類型有意義的操作。當(dāng)方法實(shí)現(xiàn)僅使用 type 的一個(gè)值時(shí),這種方法效果最好T,因?yàn)槟梢灾苯邮褂?switch guard ( v := any(vec[a]).(type)) 中的變量。當(dāng)您T在 switch guard 中的值旁邊有更多值時(shí),它就不再漂亮了,因?yàn)槟仨殕为?dú)轉(zhuǎn)換和斷言所有這些值:
func (vec Vec[T]) Less(a, b int) bool {
switch v := any(vec[a]).(type) {
case int64:
return v < any(vec[b]).(int64)
case time.Time:
return v.Before(any(vec[b]).(time.Time))
// more cases...
}
return false
}
用方法
參數(shù)化包含方法的接口并將其約束T為支持的類型。然后將Vector類型參數(shù)約束為兩者。這個(gè)的優(yōu)點(diǎn)是確保Vector不能使用您忘記實(shí)現(xiàn)Less(T) bool的類型實(shí)例化并擺脫類型斷言,否則可能會(huì)在運(yùn)行時(shí)出現(xiàn)恐慌。
type Lesser[T SupportedType] interface {
Less(T) bool
}
type Vec[T interface { SupportedType; Lesser[T] }] []T
func (vec Vec[T]) Less(a, b int) bool {
return vec[a].Less(vec[b])
}
使用方法和預(yù)先聲明的類型
不可能的。考慮以下:
type SupportedTypes interface {
// exact predeclared types
int | string
}
type Lesser[T SupportedTypes] interface {
Less(T) bool
}
約束Lesser有一個(gè)空類型集,因?yàn)榧萯nt不能也string不能有方法。所以在這里你回到了“精確類型和無方法”的情況。
具有近似類型 ( ~T)
將上面的約束條件改成近似類型:
type SupportedTypes interface {
// approximate types
~int | ~string
}
type Lesser[T SupportedTypes] interface {
Less(T) bool
}
類型開關(guān)不是一個(gè)選項(xiàng),因?yàn)閏ase ~int:它不合法。約束上存在的方法會(huì)阻止您使用預(yù)先聲明的類型進(jìn)行實(shí)例化:
Vector[MyInt8]{} // ok when MyInt8 implements Lesser
Vector[int8] // doesn't compile, int8 can't implement Lesser
所以我看到的選項(xiàng)是:
強(qiáng)制客戶端代碼使用定義的類型,在許多情況下這可能很好
將約束的范圍縮小到支持相同操作的類型
反射(用于查看性能損失是否對(duì)您來說太多的基準(zhǔn)),但反射實(shí)際上無法找到基礎(chǔ)類型,因此您只能使用reflect.Kindor進(jìn)行一些黑客攻擊CanConvert。
當(dāng)/如果該提案通過時(shí),這可能會(huì)改善并可能勝過其他選項(xiàng)。
- 2 回答
- 0 關(guān)注
- 108 瀏覽
添加回答
舉報(bào)