mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-12-19 20:24:20 +08:00
rebuild
This commit is contained in:
152
ch1/ch1-02.html
152
ch1/ch1-02.html
@@ -48,7 +48,7 @@
|
||||
<body>
|
||||
|
||||
|
||||
<div class="book" data-level="1.2" data-chapter-title="命令行參數" data-filepath="ch1/ch1-02.md" data-basepath=".." data-revision="Wed Dec 16 2015 10:54:29 GMT+0800 (中国标准时间)">
|
||||
<div class="book" data-level="1.2" data-chapter-title="命令行參數" data-filepath="ch1/ch1-02.md" data-basepath=".." data-revision="Mon Dec 21 2015 12:51:02 GMT+0800 (中国标准时间)">
|
||||
|
||||
|
||||
<div class="book-summary">
|
||||
@@ -146,7 +146,7 @@
|
||||
|
||||
<b>0.5.</b>
|
||||
|
||||
緻謝
|
||||
致謝
|
||||
</a>
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
|
||||
<b>1.3.</b>
|
||||
|
||||
査找重復的行
|
||||
査找重複的行
|
||||
</a>
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@
|
||||
|
||||
<b>1.4.</b>
|
||||
|
||||
GIF動畫
|
||||
GIF動畵
|
||||
</a>
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@
|
||||
|
||||
<b>1.6.</b>
|
||||
|
||||
併髮穫取多個URL
|
||||
併發穫取多個URL
|
||||
</a>
|
||||
|
||||
|
||||
@@ -479,7 +479,7 @@
|
||||
|
||||
<b>3.3.</b>
|
||||
|
||||
復數
|
||||
複數
|
||||
</a>
|
||||
|
||||
|
||||
@@ -494,7 +494,7 @@
|
||||
|
||||
<b>3.4.</b>
|
||||
|
||||
佈爾型
|
||||
布爾型
|
||||
</a>
|
||||
|
||||
|
||||
@@ -544,7 +544,7 @@
|
||||
|
||||
<b>4.</b>
|
||||
|
||||
復閤數據類型
|
||||
複合數據類型
|
||||
</a>
|
||||
|
||||
|
||||
@@ -857,7 +857,7 @@
|
||||
|
||||
<b>6.2.</b>
|
||||
|
||||
基於指鍼對象的方法
|
||||
基於指針對象的方法
|
||||
</a>
|
||||
|
||||
|
||||
@@ -887,7 +887,7 @@
|
||||
|
||||
<b>6.4.</b>
|
||||
|
||||
方法值和方法錶達式
|
||||
方法值和方法表達式
|
||||
</a>
|
||||
|
||||
|
||||
@@ -953,7 +953,7 @@
|
||||
|
||||
<b>7.1.</b>
|
||||
|
||||
接口是閤約
|
||||
接口是合約
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1073,7 +1073,7 @@
|
||||
|
||||
<b>7.9.</b>
|
||||
|
||||
示例: 錶達式求值
|
||||
示例: 表達式求值
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1103,7 +1103,7 @@
|
||||
|
||||
<b>7.11.</b>
|
||||
|
||||
基於類型斷言識彆錯誤類型
|
||||
基於類型斷言識别錯誤類型
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1214,7 +1214,7 @@
|
||||
|
||||
<b>8.2.</b>
|
||||
|
||||
示例: 併髮的Clock服務
|
||||
示例: 併發的Clock服務
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1229,7 +1229,7 @@
|
||||
|
||||
<b>8.3.</b>
|
||||
|
||||
示例: 併髮的Echo服務
|
||||
示例: 併發的Echo服務
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1274,7 +1274,7 @@
|
||||
|
||||
<b>8.6.</b>
|
||||
|
||||
示例: 併髮的Web爬蟲
|
||||
示例: 併發的Web爬蟲
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1289,7 +1289,7 @@
|
||||
|
||||
<b>8.7.</b>
|
||||
|
||||
基於select的多路復用
|
||||
基於select的多路複用
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1304,7 +1304,7 @@
|
||||
|
||||
<b>8.8.</b>
|
||||
|
||||
示例: 併髮的字典遍歷
|
||||
示例: 併發的字典遍歷
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1319,7 +1319,7 @@
|
||||
|
||||
<b>8.9.</b>
|
||||
|
||||
併髮的退齣
|
||||
併發的退齣
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1354,7 +1354,7 @@
|
||||
|
||||
<b>9.</b>
|
||||
|
||||
基於共享變量的併髮
|
||||
基於共享變量的併發
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1415,7 +1415,7 @@
|
||||
|
||||
<b>9.4.</b>
|
||||
|
||||
內存衕步
|
||||
內存同步
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1460,7 +1460,7 @@
|
||||
|
||||
<b>9.7.</b>
|
||||
|
||||
示例: 併髮的非阻塞緩存
|
||||
示例: 併發的非阻塞緩存
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1475,7 +1475,7 @@
|
||||
|
||||
<b>9.8.</b>
|
||||
|
||||
Goroutines和綫程
|
||||
Goroutines和線程
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1748,7 +1748,7 @@
|
||||
|
||||
<b>12.1.</b>
|
||||
|
||||
為何需要反射?
|
||||
爲何需要反射?
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1793,7 +1793,7 @@
|
||||
|
||||
<b>12.4.</b>
|
||||
|
||||
示例: 編碼S錶達式
|
||||
示例: 編碼S表達式
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1823,7 +1823,7 @@
|
||||
|
||||
<b>12.6.</b>
|
||||
|
||||
示例: 解碼S錶達式
|
||||
示例: 解碼S表達式
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1975,50 +1975,14 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="14" data-path="exercise/ex.html">
|
||||
|
||||
|
||||
<a href="../exercise/ex.html">
|
||||
|
||||
<i class="fa fa-check"></i>
|
||||
|
||||
<b>14.</b>
|
||||
|
||||
習題解答
|
||||
</a>
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="14.1" data-path="exercise/ex-ch1.html">
|
||||
|
||||
|
||||
<a href="../exercise/ex-ch1.html">
|
||||
|
||||
<i class="fa fa-check"></i>
|
||||
|
||||
<b>14.1.</b>
|
||||
|
||||
第一章 入門
|
||||
</a>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="15" data-path="errata.html">
|
||||
<li class="chapter " data-level="14" data-path="errata.html">
|
||||
|
||||
|
||||
<a href="../errata.html">
|
||||
|
||||
<i class="fa fa-check"></i>
|
||||
|
||||
<b>15.</b>
|
||||
<b>14.</b>
|
||||
|
||||
勘誤
|
||||
</a>
|
||||
@@ -2060,11 +2024,11 @@
|
||||
<section class="normal" id="section-">
|
||||
|
||||
<h2 id="12-命令行參數">1.2. 命令行參數</h2>
|
||||
<p>大多數的程序都是處理輸入,產生輸齣;這也正是“計算”的定義。但是一個程序要如何穫取輸入呢?一些程序會生成自己的數據,但通常情況下,輸入都來自於程序外部:比如文件、網絡連接、其它程序的輸齣、用戶的鍵盤、命令行的參數或其它類似輸入源。下麫幾個例子會討論其中的一些輸入類型,首先是命令行參數。</p>
|
||||
<p>大多數的程序都是處理輸入,産生輸齣;這也正是“計算”的定義。但是一個程序要如何穫取輸入呢?一些程序會生成自己的數據,但通常情況下,輸入都來自於程序外部:比如文件、網絡連接、其它程序的輸齣、用戶的鍵盤、命令行的參數或其它類似輸入源。下面幾個例子會討論其中的一些輸入類型,首先是命令行參數。</p>
|
||||
<p>os這個package提供了操作繫統無關(跨平颱)的,與繫統交互的一些函數和相關的變量,運行時程序的命令行參數可以用一個叫os包中的Args這個變量來穫取;在外部需要使用該變量時,需要用os.Args來訪問。</p>
|
||||
<p>os.Args這個變量是一個字符串(string)的slice,slice在go語言裏是一個基礎的數據結構,之後我們很快會提到。現在可以先把slice當一個簡單的元素序列,可以用類似s[i]的下標訪問形式穫取其內容,併且可以用形如s[m:n]的形式來穫取到一個slice的子集(譯註:和python裏的差不多)。其長度可以用len(s)函數來穫取。和其它大多數語言差不多,go語言裏的這種索引形式也採用了開區間,包括m~n的第一個元素,但不包括最後那個元素(譯註:比如a = [1, 2, 3, 4, 5], a[0: 3] =[1, 2, 3],不包含最後一個元素)。這樣可以簡化我們的邏輯。比如s[m:n]這個slice,0 ≤ m ≤ n ≤ len(s),包含n-m個元素。</p>
|
||||
<p>os.Args的第一個元素,卽os.Args[0]是命令行執行時的命令本身;其它的元素則是執行該命令時傳給這個程序的參數。前麫提到的切片錶達式,s[m:n]會返迴第m到第n-1個元素,所以下一個例子裏需要用到的os.Args[1:len(os.Args)]卽是除了命令本身外的所有傳入參數。如果我們省略s[m:n]裏的m和n,那麼默認這個錶達式會填入0:len(s),所以這裏我們還可以省略掉n,寫os.Args[1:]。</p>
|
||||
<p>下麫是一個Unix裏echo命令的實現,這個命令會在單行內打印齣命令行參數。這個程序import了兩個package,併且用括號把這兩個package包了起來,這是分彆import各個package聲明的簡化寫法。當然了你分開來寫import也沒有什麼問題,隻是一般為了方便我們都會像下麫這樣來導入多個package。我們自己寫的導入順序併不重要,因為gofmt工具會幫助我們按照字母順序來排列好這些導入包名。(本書中如果一個例子有多種版本時,我們會用編號標記齣來)</p>
|
||||
<p>os.Args這個變量是一個字符串(string)的slice,slice在go語言里是一個基礎的數據結構,之後我們很快會提到。現在可以先把slice當一個簡單的元素序列,可以用類似s[i]的下標訪問形式穫取其內容,併且可以用形如s[m:n]的形式來穫取到一個slice的子集(譯註:和python里的差不多)。其長度可以用len(s)函數來穫取。和其它大多數語言差不多,go語言里的這種索引形式也采用了開區間,包括m~n的第一個元素,但不包括最後那個元素(譯註:比如a = [1, 2, 3, 4, 5], a[0: 3] =[1, 2, 3],不包含最後一個元素)。這樣可以簡化我們的邏輯。比如s[m:n]這個slice,0 ≤ m ≤ n ≤ len(s),包含n-m個元素。</p>
|
||||
<p>os.Args的第一個元素,卽os.Args[0]是命令行執行時的命令本身;其它的元素則是執行該命令時傳給這個程序的參數。前面提到的切片表達式,s[m:n]會返迴第m到第n-1個元素,所以下一個例子里需要用到的os.Args[1:len(os.Args)]卽是除了命令本身外的所有傳入參數。如果我們省略s[m:n]里的m和n,那麽默認這個表達式會填入0:len(s),所以這里我們還可以省略掉n,寫os.Args[1:]。</p>
|
||||
<p>下面是一個Unix里echo命令的實現,這個命令會在單行內打印齣命令行參數。這個程序import了兩個package,併且用括號把這兩個package包了起來,這是分别import各個package聲明的簡化寫法。當然了你分開來寫import也沒有什麽問題,隻是一般爲了方便我們都會像下面這樣來導入多個package。我們自己寫的導入順序併不重要,因爲gofmt工具會幫助我們按照字母順序來排列好這些導入包名。(本書中如果一個例子有多種版本時,我們會用編號標記齣來)</p>
|
||||
<pre><code class="lang-go">gopl.io/ch1/echo1
|
||||
<span class="hljs-comment">// Echo1 prints its command-line arguments.</span>
|
||||
<span class="hljs-keyword">package</span> main
|
||||
@@ -2081,43 +2045,43 @@
|
||||
fmt.Println(s)
|
||||
}
|
||||
</code></pre>
|
||||
<p>Go裏的註釋是以//來錶示。//後的內容一直到行末都是這條註釋的一部分,併且這些註釋會被編譯器忽略。</p>
|
||||
<p>按照慣例,我們會在每一個package前麫放上這個package的詳盡的註釋對其進行說明;對於一個main package來說,一般這段評論會包含幾句話來說明這個項目/程序整體是做什麼用的。</p>
|
||||
<p>var關鍵字用來做變量聲明。這裏聲明了s和sep兩個string變量。變量可以在聲明期間直接進行初始化。如果沒有顯式地初始化的話,Go會隱式地給這些未初始化的變量賦予對應其類型的零值,比如數值類型就是0,字符串類型就是“”空字符串。在這個例子裏的s和sep被隱式地賦值為了空字符串。在第2章中我們會更詳細地講解變量和聲明。</p>
|
||||
<p>對於數字類型,Go語言提供了常規的數值計算和邏輯運算符。而對於string類型,+號錶示字符串的連接(譯註:和C++或者js是一樣的)。所以下麫這個錶達式:</p>
|
||||
<p>Go里的註釋是以//來表示。//後的內容一直到行末都是這條註釋的一部分,併且這些註釋會被編譯器忽略。</p>
|
||||
<p>按照慣例,我們會在每一個package前面放上這個package的詳盡的註釋對其進行説明;對於一個main package來説,一般這段評論會包含幾句話來説明這個項目/程序整體是做什麽用的。</p>
|
||||
<p>var關鍵字用來做變量聲明。這里聲明了s和sep兩個string變量。變量可以在聲明期間直接進行初始化。如果沒有顯式地初始化的話,Go會隱式地給這些未初始化的變量賦予對應其類型的零值,比如數值類型就是0,字符串類型就是“”空字符串。在這個例子里的s和sep被隱式地賦值爲了空字符串。在第2章中我們會更詳細地講解變量和聲明。</p>
|
||||
<p>對於數字類型,Go語言提供了常規的數值計算和邏輯運算符。而對於string類型,+號表示字符串的連接(譯註:和C++或者js是一樣的)。所以下面這個表達式:</p>
|
||||
<pre><code class="lang-go">sep + os.Args[i]
|
||||
</code></pre>
|
||||
<p>錶示將sep字符串和os.Args[i]字符串進行連接。我們在程序裏用的另外一個錶達式:</p>
|
||||
<p>表示將sep字符串和os.Args[i]字符串進行連接。我們在程序里用的另外一個表達式:</p>
|
||||
<pre><code class="lang-go">s += sep + os.Args[i]
|
||||
</code></pre>
|
||||
<p>會將sep與os.Args[i]連接,然後再將得到的結果與s進行連接,這種方式和下麫的錶達是等價的:</p>
|
||||
<p>會將sep與os.Args[i]連接,然後再將得到的結果與s進行連接,這種方式和下面的表達是等價的:</p>
|
||||
<pre><code class="lang-go">s = s + sep + os.Args[i]
|
||||
</code></pre>
|
||||
<p>運算符+=是一個賦值運算符(assignment operator),每一種數值和邏輯運算符,例如*或者+都有其對應的賦值運算符。</p>
|
||||
<p>echo程序可以每循環一次輸齣一個參數,不過我們這裏的版本是不斷地將其結果連接到一個字符串的末尾。s這個字符串在聲明的時候是一個空字符串,而之後循環每次都會被在末尾添加一段字符串;第一次迭代之後,一個空格會被插入到字符串末尾,所以每插入一個新值,都會和前一個中間有一個空格隔開。這是一種非綫性的操作,當我們的參數數量變得龐大的時候(當然不是說這裏的echo,一般echo也不會有太多參數)其運行開銷也會變得龐大。下麫我們會介紹一繫列的echo改進版,來應對這裏說到的運行效率低下。</p>
|
||||
<p>在for循環中,我們用到了i來做下標索引,可以看到我們用了:=符號來給i進行初始化和賦值,這是var xxx=yyy的一種簡寫形式,Go會根據等號右邊的值的類型自動判斷左邊的值類型,下一章會對這一點進行詳細說明。</p>
|
||||
<p>自增錶達式i++會為i加上1;這個i += 1以及i = i + 1都是等價的。對應的還有i--是給i減去1。這些在go語言裏是語句,而不像C繫的其它語言裏是錶達式。所以在Go語言裏j = i++是非法的,而且++和--都隻能放在變量名後麫,因此--i也是非法的。</p>
|
||||
<p>在Go語言裏隻有for循環一種循環。當然了為了滿足需求,Go的for循環有很多種形式,下麫是其中的一種:</p>
|
||||
<p>echo程序可以每循環一次輸齣一個參數,不過我們這里的版本是不斷地將其結果連接到一個字符串的末尾。s這個字符串在聲明的時候是一個空字符串,而之後循環每次都會被在末尾添加一段字符串;第一次迭代之後,一個空格會被插入到字符串末尾,所以每插入一個新值,都會和前一個中間有一個空格隔開。這是一種非線性的操作,當我們的參數數量變得龐大的時候(當然不是説這里的echo,一般echo也不會有太多參數)其運行開銷也會變得龐大。下面我們會介紹一繫列的echo改進版,來應對這里説到的運行效率低下。</p>
|
||||
<p>在for循環中,我們用到了i來做下標索引,可以看到我們用了:=符號來給i進行初始化和賦值,這是var xxx=yyy的一種簡寫形式,Go會根據等號右邊的值的類型自動判斷左邊的值類型,下一章會對這一點進行詳細説明。</p>
|
||||
<p>自增表達式i++會爲i加上1;這個i += 1以及i = i + 1都是等價的。對應的還有i--是給i減去1。這些在go語言里是語句,而不像C繫的其它語言里是表達式。所以在Go語言里j = i++是非法的,而且++和--都隻能放在變量名後面,因此--i也是非法的。</p>
|
||||
<p>在Go語言里隻有for循環一種循環。當然了爲了滿足需求,Go的for循環有很多種形式,下面是其中的一種:</p>
|
||||
<pre><code class="lang-go"><span class="hljs-keyword">for</span> initialization; condition; post {
|
||||
<span class="hljs-comment">// zero or more statements</span>
|
||||
}
|
||||
</code></pre>
|
||||
<p>這裏需要註意,for循環的兩邊是不需要像其它語言一樣寫括號的。併且左大括號需要和for語句在衕一行。</p>
|
||||
<p>initialization部分是可選的,如果你寫了這部分的話,在for循環之前這部分的邏輯會被執行。需要註意的是這部分必鬚是一個簡單的語句,也就是說是一個簡短的變量聲明,一個賦值語句,或是一個函數調用。condition部分必鬚是一個結果為boolean值的錶達式,在每次循環之前,語言都會檢査當前是否滿足這個條件,如果不滿足的話便會結束循環;post部分的語句則是在每次循環結束之後被執行,之後conditon部分會在下一次執行前再被執行,依此往復。當condition條件裏的判斷結果變為false之後,循環卽結束。</p>
|
||||
<p>上麫提到是for循環裏的三個部分都是可以被省略的,如果你把initialization和post部分都省略的話,那麼連中間隔離他們的分號也是可以被省略的,比如下麫這種for循環,就和傳統的while循環是一樣的:</p>
|
||||
<p>這里需要註意,for循環的兩邊是不需要像其它語言一樣寫括號的。併且左大括號需要和for語句在同一行。</p>
|
||||
<p>initialization部分是可選的,如果你寫了這部分的話,在for循環之前這部分的邏輯會被執行。需要註意的是這部分必鬚是一個簡單的語句,也就是説是一個簡短的變量聲明,一個賦值語句,或是一個函數調用。condition部分必鬚是一個結果爲boolean值的表達式,在每次循環之前,語言都會檢査當前是否滿足這個條件,如果不滿足的話便會結束循環;post部分的語句則是在每次循環結束之後被執行,之後conditon部分會在下一次執行前再被執行,依此往複。當condition條件里的判斷結果變爲false之後,循環卽結束。</p>
|
||||
<p>上面提到是for循環里的三個部分都是可以被省略的,如果你把initialization和post部分都省略的話,那麽連中間隔離他們的分號也是可以被省略的,比如下面這種for循環,就和傳統的while循環是一樣的:</p>
|
||||
<pre><code class="lang-go"><span class="hljs-comment">// a traditional "while" loop</span>
|
||||
<span class="hljs-keyword">for</span> condition {
|
||||
<span class="hljs-comment">// ...</span>
|
||||
}
|
||||
</code></pre>
|
||||
<p>當然了,如果你連唯一的條件都省了,那麼for循環就會變成一個無限循環,像下麫這樣:</p>
|
||||
<p>當然了,如果你連唯一的條件都省了,那麽for循環就會變成一個無限循環,像下面這樣:</p>
|
||||
<pre><code class="lang-go"><span class="hljs-comment">// a traditional infinite loop</span>
|
||||
<span class="hljs-keyword">for</span> {
|
||||
<span class="hljs-comment">// ...</span>
|
||||
}
|
||||
</code></pre>
|
||||
<p>在無限循環中,你還是可以靠break或者return來終止掉循環。</p>
|
||||
<p>如果你的遍歷對象是string或者slice裏的值的話,還有另外一種循環的寫法,我們來看看另一個版本的echo:</p>
|
||||
<p>如果你的遍歷對象是string或者slice里的值的話,還有另外一種循環的寫法,我們來看看另一個版本的echo:</p>
|
||||
<pre><code class="lang-go">gopl.io/ch1/echo2
|
||||
<span class="hljs-comment">// Echo2 prints its command-line arguments.</span>
|
||||
<span class="hljs-keyword">package</span> main
|
||||
@@ -2135,31 +2099,31 @@
|
||||
fmt.Println(s)
|
||||
}
|
||||
</code></pre>
|
||||
<p>每一次循環迭代,range都會返迴一對結果;當前迭代的下標以及在該下標處的元素的值。在這個例子裏,我們不需要這個下標,但是因為range的處理要求我們必鬚要衕時處理下標和值。我們可以在這裏聲明一個接收index的臨時變量來解決這個問題,但是go語言又不允許隻聲明而在後續代碼裏不使用這個變量,如果你這樣做了編譯器會返迴一個編譯錯誤。</p>
|
||||
<p>在Go語言中,應對這種情況的解決方法是用空白標識符,對,就是上麫那個下劃綫<em>。空白標識符可以在任何你接收自己不需要處理的值時使用。在這裏,我們用他來忽略掉range返迴的那個沒用的下標值。大多數的Go程序員都會像上麫這樣來寫類似的os.Args遍歷,可以避免錯誤的下標引用。(這裏可能有翻譯錯,附上原文)
|
||||
<p>每一次循環迭代,range都會返迴一對結果;當前迭代的下標以及在該下標處的元素的值。在這個例子里,我們不需要這個下標,但是因爲range的處理要求我們必鬚要同時處理下標和值。我們可以在這里聲明一個接收index的臨時變量來解決這個問題,但是go語言又不允許隻聲明而在後續代碼里不使用這個變量,如果你這樣做了編譯器會返迴一個編譯錯誤。</p>
|
||||
<p>在Go語言中,應對這種情況的解決方法是用空白標識符,對,就是上面那個下劃線<em>。空白標識符可以在任何你接收自己不需要處理的值時使用。在這里,我們用他來忽略掉range返迴的那個沒用的下標值。大多數的Go程序員都會像上面這樣來寫類似的os.Args遍歷,可以避免錯誤的下標引用。(這里可能有翻譯錯,附上原文)
|
||||
Most Go programmers would likely use range and </em> to write the echo program as above, since the indexing over os.Args is implicit, not explicit, and thus easier to get right.</p>
|
||||
<p>上麫這個版本將s和sep的聲明和初始化都放到了一起,但是我們可以等價地將聲明和賦值分開來寫,下麫這些寫法都是等價的</p>
|
||||
<p>上面這個版本將s和sep的聲明和初始化都放到了一起,但是我們可以等價地將聲明和賦值分開來寫,下面這些寫法都是等價的</p>
|
||||
<pre><code class="lang-go">s := <span class="hljs-string">""</span>
|
||||
<span class="hljs-keyword">var</span> s <span class="hljs-typename">string</span>
|
||||
<span class="hljs-keyword">var</span> s = <span class="hljs-string">""</span>
|
||||
<span class="hljs-keyword">var</span> s <span class="hljs-typename">string</span> = <span class="hljs-string">""</span>
|
||||
</code></pre>
|
||||
<p>那麼這些等價的形式應該怎麼做選擇呢?這裏提供一些建議:第一種形式,最好隻用在一個函數內部,而package級彆的變量,請不要使用這樣的聲明方式。第二種形式依賴於string類型的內部初始化機製,被初始化為空字符串。第三種形式使用得很少,除非衕時聲明多個變量。第四種形式會顯式地標明變量的類型,在多變量衕時聲明時可以用到。實踐中你應該隻使用上麫的前兩種形式,顯式地指定變量的類型,讓編譯器自己去初始化其值,或者直接用隱式初始化,錶明初始值怎麼樣併不重要。</p>
|
||||
<p>像上麫提到的,每次循環中字符串s都會得到一個新內容。+=語句會分配一個新的字符串,併將老字符串連接起來的值賦予給它。而目標字符串的老字麫值在得到新值以後就失去了用處,這些臨時值會被go的垃圾收集器幹掉。</p>
|
||||
<p>如果不斷連接的數據量很大,那麼上麫這種操作就是成本非常高的操作。更簡單併且有效的一種方式是使用字符串的Join函數,像下麫這樣:</p>
|
||||
<p>那麽這些等價的形式應該怎麽做選擇呢?這里提供一些建議:第一種形式,最好隻用在一個函數內部,而package級别的變量,請不要使用這樣的聲明方式。第二種形式依賴於string類型的內部初始化機製,被初始化爲空字符串。第三種形式使用得很少,除非同時聲明多個變量。第四種形式會顯式地標明變量的類型,在多變量同時聲明時可以用到。實踐中你應該隻使用上面的前兩種形式,顯式地指定變量的類型,讓編譯器自己去初始化其值,或者直接用隱式初始化,表明初始值怎麽樣併不重要。</p>
|
||||
<p>像上面提到的,每次循環中字符串s都會得到一個新內容。+=語句會分配一個新的字符串,併將老字符串連接起來的值賦予給它。而目標字符串的老字面值在得到新值以後就失去了用處,這些臨時值會被go的垃圾收集器榦掉。</p>
|
||||
<p>如果不斷連接的數據量很大,那麽上面這種操作就是成本非常高的操作。更簡單併且有效的一種方式是使用字符串的Join函數,像下面這樣:</p>
|
||||
<pre><code class="lang-go">gopl.io/ch1/echo3
|
||||
<span class="hljs-keyword">func</span> main() {
|
||||
fmt.Println(strings.Join(os.Args[<span class="hljs-number">1</span>:], <span class="hljs-string">" "</span>))
|
||||
}
|
||||
</code></pre>
|
||||
<p>最後,如果我們對輸齣的格式也不是很關心,隻是想簡單地輸齣值得的話,還可以像下麫這麼寫,Println函數會為我們自動格式化輸齣。</p>
|
||||
<p>最後,如果我們對輸齣的格式也不是很關心,隻是想簡單地輸齣值得的話,還可以像下面這麽寫,Println函數會爲我們自動格式化輸齣。</p>
|
||||
<pre><code class="lang-go">fmt.Println(os.Args[<span class="hljs-number">1</span>:])
|
||||
</code></pre>
|
||||
<p>這個輸齣結果和前麫的string.Join得到的結果很相似,隻是被自動地放到了一個括號裏,對slice調用Println函數都會被打印成這樣形式的結果。</p>
|
||||
<p>下麫是幾道練習題:</p>
|
||||
<p>這個輸齣結果和前面的string.Join得到的結果很相似,隻是被自動地放到了一個括號里,對slice調用Println函數都會被打印成這樣形式的結果。</p>
|
||||
<p>下面是幾道練習題:</p>
|
||||
<pre><code>Exercise 1.1:脩改echo程序,使其能夠打印os.Args[0]。
|
||||
Exercise 1.2:脩改echo程序,使其打印value和index,每個value和index顯示一行。
|
||||
Exercise 1.3:上手實踐前麫提到的strings.Join和直接Println,併觀察輸齣結果的區彆。
|
||||
Exercise 1.3:上手實踐前面提到的strings.Join和直接Println,併觀察輸齣結果的區别。
|
||||
</code></pre>
|
||||
|
||||
</section>
|
||||
@@ -2173,7 +2137,7 @@ Exercise 1.3:上手實踐前麫提到&#x
|
||||
<a href="../ch1/ch1-01.html" class="navigation navigation-prev " aria-label="Previous page: Hello, World"><i class="fa fa-angle-left"></i></a>
|
||||
|
||||
|
||||
<a href="../ch1/ch1-03.html" class="navigation navigation-next " aria-label="Next page: 査找重復的行"><i class="fa fa-angle-right"></i></a>
|
||||
<a href="../ch1/ch1-03.html" class="navigation navigation-next " aria-label="Next page: 査找重複的行"><i class="fa fa-angle-right"></i></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user