我想寫一個通用的 equals
方法,其工作原理如下:
func equals[T any](a, b T) bool { if hasEqualsMethod(T) { return a.Equals(b) else if isComparable(T) { return a == b } panic("type cannot be compared") }
為此,我創建了一個介面 comparable
:
type Comparable[T any] interface { // Equals returns true if the receiver and the argument are equal. Equals(T) bool }
我可以檢查 equals 的參數是否實作了這個 comparable
接口,如下所示:
func equals[T any](a, b T) bool { aComp, ok := any(a).(Comparable[T]) if ok { return aComp.Equals(b) } ...
但是,到目前為止,我發現不可能找出 a
是否也滿足 comparable
約束並將其轉換為可以使用 ==
的內容。
有沒有辦法找出泛型類型T any
在運行時是否是comparable
,如果是,則使用==
進行比較?
我可以限制我的整個程式碼僅適用於comparable
泛型類型,但我想讓使用者可以手動新增equals
方法,如果他們的類型恰好不是 comparable
(例如,因為它是基於切片) )。
如果它使用相等運算子進行編譯,則它是可比較的。受 any
約束的類型參數在定義上是不可比較的:它實際上可以是任何內容,包括 func() error
。
因此不可能使用靜態型別來寫 equals
函數。您必須使用反射或僅接受實現「相等」介面的參數,例如您自己的 Comparable[T any]
。
透過反射,您可以使用Value#Comparable
:
func equals[T any](a, b T) bool { v := reflect.ValueOf(a) if v.Comparable() { u := reflect.ValueOf(b) return v.Equal(u) } panic("type cannot be compared") }
在這種情況下,使用泛型可能有助於在編譯時確保a
和b
具有相同的確切類型,因此v.Equal(u)
不是毫無意義的,而不是宣告equals(a, b any)
。
使用「equaler」接口,您必須提供實作它的命名類型,以便轉換預先聲明的類型並呼叫它們的方法:
func main() { fmt.Println(equals(EqualerFloat64(5.57), EqualerFloat64(5.57))) } type Equaler[T any] interface { Equal(T) bool } type EqualerFloat64 float64 func (f EqualerFloat64) Equal(f2 EqualerFloat64) bool { return f == f2 } func equals[T Equaler[T]](a, b T) bool { return a.Equal(b) }
以上是如何確定泛型類型在運行時是否「可比較」?的詳細內容。更多資訊請關注PHP中文網其他相關文章!