make loop

This commit is contained in:
chai2010
2015-12-28 15:57:07 +08:00
parent 77148f84d4
commit ba7261d140
25 changed files with 44 additions and 44 deletions

View File

@@ -48,7 +48,7 @@ Hello, 世界
gopl.io/ch1/helloworld
```
如果你執行 `go get gopl.io/ch1/helloworld` 命令go命令能夠自己從網上取到這些代碼譯註需要先安裝Git或Hg之類的版本管理工具併將對應的命令添加到PATH環境變量中併且將這些代碼放到對應的目録中譯註序言已經提及需要先設置好GOPATH環境變量下載的代碼會放在 $GOPATH/src/gopl.io/ch1/helloworld 目録。更詳細的介紹在2.6和10.7章節中。
如果你執行 `go get gopl.io/ch1/helloworld` 命令go命令能夠自己從網上取到這些代碼譯註需要先安裝Git或Hg之類的版本管理工具併將對應的命令添加到PATH環境變量中併且將這些代碼放到對應的目録中譯註序言已經提及需要先設置好GOPATH環境變量下載的代碼會放在 $GOPATH/src/gopl.io/ch1/helloworld 目録。更詳細的介紹在2.6和10.7章節中。
我們來討論一下程序本身。Go語言的代碼是通過package來組織的package的概念和你知道的其它語言里的libraries或者modules概念比較類似。一個package會包含一個或多個.go結束的源代碼文件。每一個源文件都是以一個package xxx的聲明語句開頭的比如我們的例子里就是package main。這行聲明語句表示該文件是屬於哪一個package緊跟着是一繫列import的package名表示這個文件中引入的package。再之後是本文件本身的代碼。

View File

@@ -1,10 +1,10 @@
## 1.2. 命令行參數
大多數的程序都是處理輸入,産生輸出;這也正是“計算”的定義。但是一個程序要如何取輸入呢?一些程序會生成自己的數據,但通常情況下,輸入都來自於程序外部:比如文件、網絡連接、其它程序的輸出、用戶的鍵盤、命令行的參數或其它類似輸入源。下面幾個例子會討論其中的一些輸入類型,首先是命令行參數。
大多數的程序都是處理輸入,産生輸出;這也正是“計算”的定義。但是一個程序要如何取輸入呢?一些程序會生成自己的數據,但通常情況下,輸入都來自於程序外部:比如文件、網絡連接、其它程序的輸出、用戶的鍵盤、命令行的參數或其它類似輸入源。下面幾個例子會討論其中的一些輸入類型,首先是命令行參數。
os這個package提供了操作繫統無關跨平台與繫統交互的一些函數和相關的變量運行時程序的命令行參數可以通過os包中一個叫Args的這個變量來當在os包外部使用該變量時需要用os.Args來訪問。
os這個package提供了操作繫統無關跨平台與繫統交互的一些函數和相關的變量運行時程序的命令行參數可以通過os包中一個叫Args的這個變量來當在os包外部使用該變量時需要用os.Args來訪問。
os.Args這個變量是一個字符串string的slice譯註slice和Python語言中的切片類似是一個簡版的動態數組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]這個slice0 ≤ m ≤ n ≤ len(s)包含n-m個元素。
os.Args這個變量是一個字符串string的slice譯註slice和Python語言中的切片類似是一個簡版的動態數組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]這個slice0 ≤ m ≤ n ≤ len(s)包含n-m個元素。
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:]。

View File

@@ -33,7 +33,7 @@ func main() {
和我們前面提到的for循環一樣在if條件的兩邊我們也不需要加括號但是if表達式後的邏輯體的花括號是不能省略的。如果需要的話像其它編程語言一樣這個if表達式也可以有else部分這部分邏輯會在if中的條件結果爲false時被執行。
map是Go語言內置的key/value型數據結構這個數據結構能夠提供常數時間的存儲、取、測試操作。key可以是任意數據類型隻要該類型能夠用==運算符來進行比較string是最常用的key類型。而value類型的范圍就更大了基本上什麽類型都是可以的。這個例子中的key都是string類型value用的是int類型。我們用內置make函數來創建一個空的map當然了make方法還可以有别的用處。在4.3章中我們還會對map進行更深入的討論。
map是Go語言內置的key/value型數據結構這個數據結構能夠提供常數時間的存儲、取、測試操作。key可以是任意數據類型隻要該類型能夠用==運算符來進行比較string是最常用的key類型。而value類型的范圍就更大了基本上什麽類型都是可以的。這個例子中的key都是string類型value用的是int類型。我們用內置make函數來創建一個空的map當然了make方法還可以有别的用處。在4.3章中我們還會對map進行更深入的討論。
dup程序每次讀取輸入的一行這一行的內容會被當做一個map的key而其value值會被+1。counts[input.Text()]++這個語句和下面的兩句是等價的:
@@ -76,7 +76,7 @@ Printf有一大堆這種轉換Go語言程序員把這些叫做verb動詞
dup1中的程序還包含了一個\t和\n的格式化字符串。在字符串中會以這些特殊的轉義字符來表示不可見字符。Printf默認不會在輸出內容後加上換行符。按照慣例用來格式化的函數都會在末尾以f字母結尾譯註f後綴對應format或fmt縮寫比如log.Printffmt.Errorf同時還有一繫列對應以ln結尾的函數譯註ln後綴對應line縮寫這些函數默認以%v來格式化他們的參數併且會在輸出結束後在最後自動加上一個換行符。
許多程序從標準輸入中讀取數據像上面的例子那樣。除此之外還可能從一繫列的文件中讀取。下一個dup程序就是從標準輸入中讀到一些文件名用os.Open函數來打開每一個文件取內容的。
許多程序從標準輸入中讀取數據像上面的例子那樣。除此之外還可能從一繫列的文件中讀取。下一個dup程序就是從標準輸入中讀到一些文件名用os.Open函數來打開每一個文件取內容的。
```go
gopl.io/ch1/dup2

View File

@@ -1,8 +1,8 @@
## 1.5. 取URL
## 1.5. 取URL
對於很多現代應用來説訪問互聯網上的信息和訪問本地文件繫統一樣重要。Go語言在net這個強大package的幫助下提供了一繫列的package來做這件事情使用這些包可以更簡單地用網絡收發信息還可以建立更底層的網絡連接編寫服務器程序。在這些情景下Go語言原生的併發特性在第八章中會介紹就顯得尤其好用了。
爲了最簡單地展示基於HTTP取信息的方式下面給出一個示例程序fetch這個程序將取對應的url併將其源文本打印出來這個例子的靈感來源於curl工具譯註unix下的一個網絡相關的工具。當然了curl提供的功能更爲複雜豐富這里我們隻編寫最簡單的樣例。之後我們還會在本書中經常用到這個例子。
爲了最簡單地展示基於HTTP取信息的方式下面給出一個示例程序fetch這個程序將取對應的url併將其源文本打印出來這個例子的靈感來源於curl工具譯註unix下的一個網絡相關的工具。當然了curl提供的功能更爲複雜豐富這里我們隻編寫最簡單的樣例。之後我們還會在本書中經常用到這個例子。
```go
gopl.io/ch1/fetch
@@ -34,7 +34,7 @@ func main() {
}
```
這個程序從兩個package中導入了函數net/http和io/ioutil包http.Get函數是創建HTTP請求的函數如果取過程沒有出錯那麽會在resp這個結構體中得到訪問的請求結果。resp的Body字段包括一個可讀的服務器響應流。這之後ioutil.ReadAll函數從response中讀取到全部內容其結果保存在變量b中。resp.Body.Close這一句會關閉resp的Body流防止資源洩露Printf函數會將結果b寫出到標準輸出流中。
這個程序從兩個package中導入了函數net/http和io/ioutil包http.Get函數是創建HTTP請求的函數如果取過程沒有出錯那麽會在resp這個結構體中得到訪問的請求結果。resp的Body字段包括一個可讀的服務器響應流。這之後ioutil.ReadAll函數從response中讀取到全部內容其結果保存在變量b中。resp.Body.Close這一句會關閉resp的Body流防止資源洩露Printf函數會將結果b寫出到標準輸出流中。
```
$ go build gopl.io/ch1/fetch

View File

@@ -1,8 +1,8 @@
## 1.6. 併發取多個URL
## 1.6. 併發取多個URL
Go語言最有意思併且最新奇的特性就是其對併發編程的支持了。併發編程是一個大話題在第八章和第九章中會專門講到。這里我們隻淺嚐輒止地來體驗一下Go語言里的goroutine和channel。
下面的例子fetchall和上面的fetch程序所要做的工作是一致的但是這個fetchall的特别之處在於它會同時去取所有的URL所以這個程序的取時間不會超過執行時間最長的那一個任務而不會像前面的fetch程序一樣執行時間是所有任務執行時間之和。這次的fetchall程序隻會打印取的內容大小和經過的時間,不會像上面那樣打印出取的內容。
下面的例子fetchall和上面的fetch程序所要做的工作是一致的但是這個fetchall的特别之處在於它會同時去取所有的URL所以這個程序的取時間不會超過執行時間最長的那一個任務而不會像前面的fetch程序一樣執行時間是所有任務執行時間之和。這次的fetchall程序隻會打印取的內容大小和經過的時間,不會像上面那樣打印出取的內容。
```go
gopl.io/ch1/fetchall
@@ -65,4 +65,4 @@ main函數中用make函數創建了一個傳遞string類型參數的channel
當一個goroutine嚐試在一個channel上做send或者receive操作時這個goroutine會阻塞在調用處直到另一個goroutine往這個channel里寫入、或者接收了值這樣兩個goroutine才會繼續執行操作channel完成之後的邏輯。在這個例子中每一個fetch函數在執行時都會往channel里發送一個值(ch <- expression)主函數接收這些值(<-ch)。這個程序中我們用main函數來所有fetch函數傳迴的字符串可以避免在goroutine異步執行時同時結束
**練習 1.10** 找一個數據量比較大的網站用本小節中的程序調研網站的緩存策略對每個URL執行兩遍請求査看兩次時間是否有較大的差别併且每次取到的響應內容是否一致脩改本節中的程序將響應結果輸出以便於進行對比
**練習 1.10** 找一個數據量比較大的網站用本小節中的程序調研網站的緩存策略對每個URL執行兩遍請求査看兩次時間是否有較大的差别併且每次取到的響應內容是否一致脩改本節中的程序將響應結果輸出以便於進行對比

View File

@@ -49,7 +49,7 @@ var p Point
類型聲明和命名類型會在第二章中介紹。
**指針:** Go語言提供了指針。指針是一種直接存儲了變量的內存地址的數據類型。在其它語言中比如C語言指針操作是完全不受約束的。在另外一些語言中指針一般被處理爲“引用”除了到處傳遞這些指針之外併不能對這些指針做太多事情。Go語言在這兩種范圍中取了一種平衡。指針是可見的內存地址&操作符可以返迴一個變量的內存地址,併且*操作符可以取指針指向的變量內容但是在Go語言里沒有指針運算也就是不能像c語言里可以對指針進行加或減操作。我們會在2.3.2中進行詳細介紹。
**指針:** Go語言提供了指針。指針是一種直接存儲了變量的內存地址的數據類型。在其它語言中比如C語言指針操作是完全不受約束的。在另外一些語言中指針一般被處理爲“引用”除了到處傳遞這些指針之外併不能對這些指針做太多事情。Go語言在這兩種范圍中取了一種平衡。指針是可見的內存地址&操作符可以返迴一個變量的內存地址,併且*操作符可以取指針指向的變量內容但是在Go語言里沒有指針運算也就是不能像c語言里可以對指針進行加或減操作。我們會在2.3.2中進行詳細介紹。
**方法和接口:** 方法是和命名類型關聯的一類函數。Go語言里比較特殊的是方法可以被關聯到任意一種命名類型。在第六章我們會詳細地講方法。接口是一種抽象類型這種類型可以讓我們以同樣的方式來處理不同的固有類型不用關心它們的具體實現而隻需要關註它們提供的方法。第七章中會詳細説明這些內容。