如何利用反射比較兩個物件完全相同

2021-10-05 06:41:16 字數 2792 閱讀 9285

go 語言中提供了乙個函式可以完成此項功能:

func

deepequal

(x, y inte***ce

)bool

deepequal函式的引數是兩個inte***ce,實際上也就是可以輸入任意型別,輸出 true 或者 flase 表示輸入的兩個變數是否是「深度」相等。

先明白一點,如果是不同的型別,即使是底層型別相同,相應的值也相同,那麼兩者也不是「深度」相等。

type myint int

type yourint int

func

main()

上面的**中,m, y 底層都是 int,而且值都是 1,但是兩者靜態型別不同,前者是myint,後者是yourint,因此兩者不是「深度」相等。

在原始碼裡,有對 deepequal 函式的非常清楚地注釋,列舉了不同型別,deepequal 的比較情形,這裡做乙個總結:

型別深度相等情形

array

相同索引處的元素「深度」相等

struct

相應字段,包含匯出和不匯出,「深度」相等

func

只有兩者都是 nil 時

inte***ce

兩者儲存的具體值「深度」相等

map1、都為 nil;2、非空、長度相等,指向同乙個 map 實體物件,或者相應的 key 指向的 value 「深度」相等

pointer

1、使用 == 比較的結果相等;2、指向的實體「深度」相等

slice

1、都為 nil;2、非空、長度相等,首元素指向同乙個底層陣列的相同元素,即 &x[0] == &y[0] 或者 相同索引處的元素「深度」相等

numbers, bools, strings, and channels

使用 == 比較的結果為真

一般情況下,deepequal 的實現只需要遞迴地呼叫 == 就可以比較兩個變數是否是真的「深度」相等。

但是,有一些異常情況:比如 func 型別是不可比較的型別,只有在兩個 func 型別都是 nil 的情況下,才是「深度」相等;float 型別,由於精度的原因,也是不能使用 == 比較的;包含 func 型別或者 float 型別的 struct, inte***ce, array 等。

對於指標而言,當兩個值相等的指標就是「深度」相等,因為兩者指向的內容是相等的,即使兩者指向的是 func 型別或者 float 型別,這種情況下不關心指標所指向的內容。

同樣,對於指向相同 slice, map 的兩個變數也是「深度」相等的,不關心 slice, map 具體的內容。

對於「有環」的型別,比如迴圈鍊錶,比較兩者是否「深度」相等的過程中,需要對已比較的內容作乙個標記,一旦發現兩個指標之前比較過,立即停止比較,並判定二者是深度相等的。這樣做的原因是,及時停止比較,避免陷入無限迴圈。

來看原始碼:

func

deepequal

(x, y inte***ce

)bool

v1 :=

valueof

(x) v2 :=

valueof

(y)if v1.

type()

!= v2.

type()

return

deepvalueequal

(v1, v2,

make

(map

[visit]

bool),

0)}

首先檢視兩者是否有乙個是 nil 的情況,這種情況下,只有兩者都是 nil,函式才會返回 true

接著,使用反射,獲取x,y 的反射物件,並且立即比較兩者的型別,根據前面的內容,這裡實際上是動態型別,如果型別不同,直接返回 false。

最後,最核心的內容在子函式deepvalueequal中。

**比較長,思路卻比較簡單清晰:核心是乙個 switch 語句,識別輸入引數的不同型別,分別遞迴呼叫 deepvalueequal 函式,一直遞迴到最基本的資料型別,比較 int,string 等可以直接得出 true 或者 false,再一層層地返回,最終得到「深度」相等的比較結果。

實際上,各種型別的比較套路比較相似,這裡就直接節選乙個稍微複雜一點的map型別的比較:

// deepvalueequal 函式

// ……

case map:

if v1.

isnil()

!= v2.

isnil()

if v1.

len(

)!= v2.

len(

)if v1.

pointer()

== v2.

pointer()

for_

, k :=

range v1.

mapkeys()

}return

true

// ……

和前文總結的**裡,比較 map 是否相等的思路比較一致,也不需要多說什麼。說明一點,visited是乙個 map,記錄遞迴過程中,比較過的「對」:

type visit struct

map[visit]

bool

比較過程中,一旦發現比較的「對」,已經在 map 裡出現過的話,直接判定「深度」比較結果的是true

兩個物件屬性的比較

兩個物件的引用比較可以用equal 但是兩個物件的屬性比較就比較麻煩一些,寫乙個方法,僅供參考 1 public static bool propertyequals object aobject1,object aobject2 2 27 28else if vobject1 is list vo...

比較兩個物件是否相等

using system using system.collections.generic using system.text using system.reflection namespace objectcompare public int age static class program 測試...

如何比較兩個 Schema 的異同

有的時候,dba 需要迅速找出來同乙個 oracle 資料庫上或者不同資料庫的兩個 schema 的差異.這種情況應該比較常見,比如測試資料庫發布到產品資料庫的時候,需要 dba 做頻繁的檢查。應對的辦法之一是通過 toad 這樣的 gui 工具來查詢.具體操作應該是很簡單的。oracle 自帶的 ...