一個(gè)關(guān)于“2個(gè)GolangMap是否相等”引發(fā)的反射知識(shí)點(diǎn)
先附上今日Golang每日一題:如何確認(rèn)兩個(gè) map 是否相等?
解答區(qū)大部分都是說(shuō)把map內(nèi)容先按key比對(duì),然后marshal到有序json,用string做對(duì)比
再往下看看,有老哥說(shuō)可以直接用反射做比對(duì)
package main
import(
? ?"fmt"
????????? ?"relflect")
func main() {
? ?
????var m map[string]int
? ?var n map[string]int
? ?fmt.Println(reflect.DeepEqual(m,n))
}
下面就讓我們看下反射到底能不能實(shí)現(xiàn)這一目標(biāo)
直接上測(cè)試代碼:
????
func TestEqual(t *testing.T) {
? ? x := make(map[string]int)
? ? x["test1"] = 1
? ? x["test2"] = 2
? ? m := x
? ? y := make(map[string]int)
? ? y["test1"] = 1
? ? y["test2"] = 2
? ? n := y
? ? fmt.Println(reflect.DeepEqual(m, n))????//true
? ? n["test1"] = 3
? ? fmt.Println(reflect.DeepEqual(m, n))????//false
????n["test1"] = 1
? ? n["test3"] = 3
? ? fmt.Println(reflect.DeepEqual(m, n))????//false
}
通過(guò)測(cè)試數(shù)據(jù)可以看到,是可以解決上述問(wèn)題的
那么,該接口是怎么得到這個(gè)結(jié)果的呢?
首先是外部接口 DeepEqual的實(shí)現(xiàn):
????第一步,判斷是否為nil,這步比較簡(jiǎn)單,我就不貼出來(lái)了
????第二步,運(yùn)用Value和Type判斷是否是同類型數(shù)據(jù)
?????????????v1 := ValueOf(x)
?????????????v2 := ValueOf(y)
????????????下面這句其實(shí)在第三步里有過(guò)調(diào)用,我感覺(jué)是多余的,或許是為了邏輯清晰吧
?????????????if v1.Type() != v2.Type() {????return false????}
????第三步,是封裝的私有函數(shù)調(diào)用,deepValueEqual(v1, v2, make(map[visit]bool))
? ??????????如果只以咱們這道題的map[string]int 為例的話:
?????????????deepValueEqual的調(diào)用順序如下:
????????????????????v1,v2是否有效
????????????????????v1,v2類型是否相同
????????????????????switch(v1.Kind()){
????????????????????????????case Map:
????????????????????????????????????range? v1.MapKeys()
????????????????????????????????????val1,val2 是map里相同key的值,????????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ????????????????????????????????????????????????if !deepValueEqual(val1,val2,visited) return false
????????????????????}
看到這里,想必你也明白了,其實(shí)這里沒(méi)什么玄乎的地方,解決方法跟咱們通常想到的map range比對(duì)法一模一樣,只是人家的函數(shù)更嚴(yán)謹(jǐn),更底層,更抽象