<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go 編程的三個常見問題

          共 2401字,需瀏覽 5分鐘

           ·

          2020-09-21 14:20

          via:

          https://medium.com/higher-order-functions/golang-three-common-programming-problems-3ef8baf006af
          作者:Saurabh Nayar

          四哥水平有限,如有翻譯或理解錯誤,煩請幫忙指出,感謝!

          作者在文章中列舉了使用 Go 語言過程碰到的三個常見問題,并且都給出了解決方法,一起來看下作者是怎么解決的!

          原文如下:


          每種語言都是獨一無二的。這些常見編程問題的解決方案在 Java 中是非常不同的 -- Java 是我以前最喜歡的編程語言。我敢這么說,這些問題的解決方法如果使用 Java 來解決會更加直觀。

          Go 語言有解決這些問題的獨特方法。我下面列出的解決方案最初對我來說不是很直觀,但是現(xiàn)在已經(jīng)成為我的下意識的反映。我不確定這些解決方法是否是地道的 Go 語言解決方式,老實說,我也不知道地道的方式是怎么樣的。

          也許會有更好的、不同的方式來解決這些問題 -- 我想聽聽你的想法。

          現(xiàn)在,我們一起來研究下這些問題。

          問題一

          問題:我需要維護一個集合,但是 Go 語言里面沒有集合這種數(shù)據(jù)結(jié)構(gòu)。

          解決辦法之一:可以用 Go 語言里面的 map 代替集合,map 中的 key 都是唯一的。

          package?main

          import?"fmt"

          type?Set?struct?{
          ?m?map[string]bool
          }

          func?NewSet()?Set?{
          ?m?:=?make(map[string]bool)
          ?return?Set{m:?m}
          }

          func?(s?*Set)?Contains(val?string)?bool?{
          ?_,?ok?:=?s.m[val]
          ?return?ok
          }

          func?(s?*Set)?Add(val?string)?{
          ?s.m[val]?=?true
          }

          func?(s?*Set)?Remove(val?string)?{
          ?????delete(s.m,?val)
          }

          func?main()?{
          ???s?:=?NewSet()
          ?s.Add("foo")
          ?fmt.Printf("s?has?foo:?%t.?s?has?bar:?%t\n",?s.Contains("foo"),?s.Contains("bar"))

          ??s.Remove("foo")

          ?fmt.Printf("s?has?foo:?%t.?s?has?bar:?%t\n",?s.Contains("foo"),?s.Contains("bar"))

          }

          使用 map 作為集合的底層數(shù)據(jù)結(jié)構(gòu)的好處在于,map 基于 hash 表實現(xiàn),減值查找效率高。使用這種方法可以少寫很多代碼。

          問題二

          問題:我想比較兩個值大小,但是 == 操作符有時會失效。

          解決辦法之一:我們需要理解 == 操作符的適用場景。

          包含 map 或者 slice 的結(jié)構(gòu)體

          type?ABC?struct?{
          ???a?int
          ???b?string
          ???c?[]int
          }
          Error:
          invalid?operation:?a?==?b?(struct?containing?[]int?cannot?be?compared)

          包含指針的結(jié)構(gòu)體

          從實際意義上講,指針可以進行比較,但事實總是出乎意料。

          a,?b?:=?1,?1
          fmt.Println(&a?==?&b)?//?False

          使用 reflect.DeepEqual

          //ABC?-?A?simple?type
          type?ABC?struct?{
          ???a?int
          ???b?string
          ???c?[]int
          }

          var?a?=?ABC{a:?1,?b:?"10",?c:?[]int{1,?2}}
          var?b?=?ABC{a:?1,?b:?"10",?c:?[]int{1,?2}}
          reflect.DeepEqual(a,?b)

          Example?#2
          a,?b?:=?1,?1
          fmt.Println(&a?==?&b)?//?False
          fmt.Println(reflect.DeepEqual(&a,?&b))?//?True

          reflect.DeepEqual 可以實現(xiàn)更好的效果。但是如果結(jié)構(gòu)體中 float 或者 時間字段想要忽略,則需要自己編寫比較函數(shù)。

          //ABC?-?A?simple?type
          type?ABC?struct?{
          ???a?int
          ???b?string
          ???t?time.Time?//?Ignore?time?while?comparing?to?structs
          }

          var?a?=?ABC{a:?1,?b:?"10",?t:?time.Now()}
          var?b?=?ABC{a:?1,?b:?"10",?t:?time.Now()}
          fmt.Println(a?==?b,?equals(a,?b))

          func?equals(val1,?val2?ABC)?bool?{
          ????return?val1.a?==?val2.a?&&?val1.b?==?val2.b
          }

          除非別無選擇,否則一般都不會自己編寫比較函數(shù)。但是與 == 操作符相比,是否要傾向于使用 reflect.DeepEqual。本質(zhì)上,如果 == 比較的結(jié)果為 true,則 reflect.DeepEqual 可以保證比較的結(jié)果為 true,反之為 false。所以你可以默認使用 reflect.DeepEqual,除非程序上有性能上的限制:

          func?BenchmarkOperator(t?*testing.B)?{
          ???for?i?:=?0;?i???????if?a?==?b?{
          ??????}
          ???}
          }

          func?BenchmarkReflectDeep(t?*testing.B)?{
          ???for?i?:=?0;?i???????if?reflect.DeepEqual(a,?b)?{
          ??????}
          ???}
          }
          BenchmarkOperator-8?????????44614131????????????24.8?ns/op?????????0?B/op??????????0?allocs/op
          BenchmarkReflectDeep-8????????823174??????????1558?ns/op??????????96?B/op??????????2?allocs/op

          從結(jié)果看出,== 比 reflect.DeepEqual 快多了!

          問題三

          問題:我需要使用一個 struct 作為 map 的鍵 -- ?但 struct 有想要忽略的 slice、指針或別的字段。

          解決辦法之一:Go 語言里面使用 == 操作符比較 map 的鍵,而不要使用 ?reflect.DeepEqual。

          解決問題的方法之一就是自定義 key 的創(chuàng)建邏輯。

          //Obvious?solution?that?will?not?work
          type?A?struct?{
          ????i?*int
          }

          i,?j?:=?1,?1
          a,?b?:=?A{i:?&i},?A{i:?&j}
          m?:=?map[A]bool{}
          m[a]?=?true
          _,?ok?:=?m[b]
          fmt.Println(ok)?//?False?key?b?doesn't?exist?in?map?m


          //Custom?keys-?solution
          func?customKey(a?A)?int?{
          ?return?*a.i
          }

          i,?j?:=?1,?1
          a,?b?:=?A{i:?&i},?A{i:?&j}
          m?:=?map[int]bool{}
          m[customKey(a)]?=?true
          _,?ok?:=?m[customKey(b)]
          fmt.Println(ok)//?This?will?return?true

          有獎問答

          問題:從上面問題 2 和問題 3 衍生出一個問題,如何比較兩個 map?

          key,?val?:=?"key",?"val"
          key1,?val1?:=?"key",?"val"
          abc?:=?map[*string]string{&key:?val}
          abc2?:=?map[*string]string{&key1:?val1}
          def?:=?map[string]*string{key:?&val}
          def2?:=?map[string]*string{key1:?&val1}
          fmt.Println(reflect.DeepEqual(abc,?abc2))?//false?
          fmt.Println(reflect.DeepEqual(def,?def2))?//true

          首先需要注意的是,不能使用 == 操作符比較 map,需要使用 ?reflect.DeepEqual。根據(jù) reflect.DeepEqual 的比較規(guī)則,map 的鍵使用 == 操作符比較而值會使用 reflect.DeepEqual ?遞歸比較。




          推薦閱讀



          學習交流 Go 語言,掃碼回復「進群」即可


          站長 polarisxu

          自己的原創(chuàng)文章

          不限于 Go 技術(shù)

          職場和創(chuàng)業(yè)經(jīng)驗


          Go語言中文網(wǎng)

          每天為你

          分享 Go 知識

          Go愛好者值得關(guān)注


          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  肏逼二区| 在线观看黄色国产视频 | 三级av二区| 中国免费毛片 | 性感美女视频一二三 |