天天看點

讀《Go并發程式設計實戰》第4章 流程控制方式

   一個網站的使用者管理中,一般使用者都會起一個昵稱,當然使用者A和使用者B的昵稱有可能相同,我們就使用類型為map[string]int的集合來表示,其中string代表使用者昵稱、int表示昵稱相同的人數。

       集合資料内容為:{"chen":20,   "chen長":10,   "春風":5,   "龍ge":13,   "where你are":7}。

§問題1. 從這個集合中找出隻包含中文的使用者昵稱的計數資訊

    上面集合中隻有使用者昵稱為“春風”的元素滿足條件,其它像“龍ge”、“chen長”、“where你are”都不是隻包含中文。像看程式實作:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

<code>users := map[string]</code><code>int</code><code>{</code><code>"chen"</code><code>: 20, </code><code>"chen長"</code><code>: 10, </code><code>"春風"</code><code>: 5, </code><code>"龍ge"</code><code>: 13, </code><code>"where你are"</code><code>: 7}</code>

<code>var targetCount map[string]</code><code>int</code> <code>= make(map[string]</code><code>int</code><code>)</code>

<code>for</code> <code>name, count := range users {</code>

<code>    </code><code>matched := </code><code>true</code>

<code>    </code><code>for</code> <code>_, v := range name {</code>

<code>        </code><code>if</code> <code>v &lt; </code><code>'\u4e00'</code> <code>|| v &gt; </code><code>'\u9fbf'</code> <code>{</code>

<code>            </code><code>matched = </code><code>false</code>

<code>            </code><code>break</code>

<code>        </code><code>}</code>

<code>    </code><code>}</code>

<code>    </code><code>if</code> <code>matched {</code>

<code>        </code><code>targetCount[name] = count</code>

<code>}</code>

<code>fmt.Println(targetCount)</code>

解釋一下:

第一層for循環周遊users集合,得到昵稱(name)和計數(count ):

for name, count := range users{

      // ......

}

第二層循環周遊昵稱name字元串中的每個字元,并判斷是否有非中文字元:

for _, v := range name{

      if v &lt;'\u4e00' || v &gt; '\u9fbf' {  // 該範圍下的字元為非中文字元

      }

【備注】:

    這裡由變量matched充當了标志,當出現非中文字元時,matched被賦為false,并使用break中止第二層循環,然後判斷該name是否僅為中文,若是則添加進入targetCountw集合中。

運作結果為:map[春風:5]

§問題2. 從這個集合中找出隻包含中文的使用者昵稱的計數資訊,但發現第一個非全中文的使用者昵稱的時候就停止查找。

    這裡涉及到map類型的特性問題,當使用for進行周遊users集合時,順序會出現不确定性,即第一個昵稱有可能是“chen”,也有可能是“春風”,也有可能是“龍ge”,總之是不确定的。

    假設第一個昵稱是“chen長”時,程式發現它是非全中文的昵稱,這時整個程式需要結束。

<code>    </code><code>if</code> <code>!matched {</code>

<code>        </code><code>break</code>

<code>    </code><code>} </code><code>else</code> <code>{</code>

    這個程式實作與上面基本是大同小異,不同之處在于第一層循環中的matched判斷。

    假設在第一層for循環中,第一次取到的昵稱name為“龍ge”,此時第二層for循環中會逐個字元地檢視“龍ge”這個字元串,當程式發現“龍ge”是非全中文時,matched标志被置為false,同時跑出第二層循環,然後在第一層循環中問:“取到的昵稱‘龍ge’是否為全中文?”,結果不是,于是按照題目要求就break掉程式并時跳出第一層循環。

    這裡如果您多運作一下程式,就會發現結果有可能是不同的,有時為map[],有時為map[春風:5]

§問題3. 不使用輔助辨別(如上例中的matched)解決§問題2.

    作者這裡是讓您學習break Label這個東東,是以這裡直接引用作者原話了:“我們之前說過,break語句可以與标記(Label)語句一起配合使用。”

<code>L:</code>

<code>    </code><code>for</code> <code>name, count := range users {</code>

<code>        </code><code>for</code> <code>_, v := range name {</code>

<code>            </code><code>if</code> <code>v &lt; </code><code>'\u4e00'</code> <code>|| v &gt; </code><code>'\u9fbf'</code> <code>{</code>

<code>                 </code><code>break</code> <code>L</code>

<code>            </code><code>}</code>

該程式與§問題2程式功能是相同的,隻是把标志matched移除掉了。

    一條标記語句可以成為goto語句、break語句和contiune語句的目标。标記語句中的标記隻是一個辨別符,它可以被置在任何語句的左邊以作為這個語句的标簽。标記和被标記的語句之間需要用冒号“:”來分隔,即如下所示:

L:

     for name, count := range users{

          // .....

     }

    需要注意的是,标記L也是一個辨別符,那麼當它在未被使用的時候同樣也會報告編譯錯誤。那麼怎麼使用呢?一種方法就是讓它成為break的目标,即上面示例中的break L。

    标簽L代碼塊包含了第一層for循環,第一層for循環包含了第二層for循環,是以當break L時,它是中止整個标簽L代碼塊,是以這裡會中止兩層for循環。

 對比“§問題2”和“§問題3”的兩個代碼實作,“§問題3”的代碼更簡潔一些。

§問題4.  還是解決問題1的事情,隻不過要求使用continue語句,即從這個集合中找出隻包含中文的使用者昵稱的計數資訊

由于這裡沒有更多的知識點,是以引用原文:

    實際上,Go語言中的continue語句隻能在for語句中使用。continue語句會使直接包含它的那個for循環直接進入下一次疊代,換言之,本次疊代不會執行該continue語句後面那些語句(它們被跳過了)。

<code>       </code><code>continue</code>

<code>    </code><code>targetCount[name] = count</code>

或者

<code>    </code><code>for</code> <code>name,count := range users{</code>

<code>        </code><code>for</code> <code>_, v := range name{</code>

<code>            </code><code>if</code> <code>r &lt; </code><code>'\u4e00'</code> <code>|| r &gt; </code><code>'\u9fbf'</code><code>{</code>

<code>                </code><code>continue</code> <code>L</code>

OK,在讀這個章節時,隻是感覺這個例子有點意思,是以分享給大家 :)

     本文轉自qingkechina 51CTO部落格,原文連結:http://blog.51cto.com/qingkechina/1983333,如需轉載請自行聯系原作者