1. 程式人生 > >go 聖經閱讀筆記之-入門

go 聖經閱讀筆記之-入門

go 聖經 這本書英文名為 《The Go Programming Language》

1. 簡單hello world示例

helloworld.go

package main

import "fmt"

func main() {
//列印 hello, 世界 fmt.Println("Hello, 世界") }

執行,正常情況下會輸出“Hello, 世界”:

[[email protected] src]# go run helloworld.go
Hello, 世界

如果要儲存編譯結果(helloworld)以備將來之用。 可以用build子命令:

[[email protected] src]# go build helloworld.go
[[email protected] src]# ll
總用量 1872
-rwxr-xr-x. 1 root root 1906945 1月  12 00:04 helloworld
-rw-r--r--. 1 root root      79 1月  12 00:01 helloworld.go
[[email protected] src]# ./helloworld
Hello, 世界

下面來看各行程式碼的意義:

package main:定義了包名。你必須在原始檔中非註釋的第一行指明這個檔案屬於哪個包,如:package main。package main表示一個可獨立執行的程式,每個 Go 應用程式都包含一個名為 main 的包。

import "fmt":告訴 Go 編譯器這個程式需要使用 fmt 包(的函式,或其他元素),fmt 包實現了格式化 IO(輸入/輸出)的函式。

func main() :是程式開始執行的函式。main 函式是每一個可執行程式所必須包含的,一般來說都是在啟動後第一個執行的函式。

fmt.Println(...) :可以將字串輸出到控制檯,並在最後自動增加換行字元 \n。 使用 fmt.Print("hello, world\n") 可以得到相同的結果。

//列印 hello, 世界:為註釋,Go繼承自C/C++因此註釋相同,使用//單行註釋或者/**/多行註釋。

注意:Go語言不需要在語句或者宣告的末尾新增分號, 除非一行上有多條語句

2. 命令列引數 

(1)os包以跨平臺的方式, 提供了一些與作業系統互動的函式和變數。程式的命令列引數可從os包的Args變數獲取; os包外部使用os.Args訪問該變數。

首先來看Unixecho命令的一份實現, echo把它的命令列引數列印成一行 :

// Echo1 prints its command-line arguments.
package main
import (
    "fmt"
    "os"
)

func main() {
    var s, sep string
    for i := 1; i < len(os.Args); i++ {
        s += sep + os.Args[i]
        sep = " "
    }
    fmt.Println(s)
}

這裡聲明瞭兩個string型別變數 s, sep 會被隱式的初始化為空字串(""),運算子 += 是賦值運算子。符號 := 是短變數宣告的一部分, 這是定義一個或多個變數並根據它們的初始值為這些變數賦予適當型別的語句(i := 1,初始值為1,因此 i 為int型別)。

注意:自增語句 i++ i 1; 這和 i += 1 以及 i = i + 1 都是等價的 。這裡的 i++ 是語句(C語言中是表示式),因此,j = i++ 非法, 而且++和--都只能放在變數名後面, 因此 --i 也非法,注意和C語言之間的區別。

(2)for 迴圈

1)for 迴圈的第一種形式

Go語言只有for迴圈這一種迴圈語句。 for迴圈有多種形式, 其中一種如下所示:

for initialization; condition; post {
// zero or more statements
}

for迴圈三個部分不需括號包圍。 大括號強制要求, 左大括號必須和post語句在同一行。for迴圈的這三個部分每個都可以省略 ,如果連 condition 也省略了就變成一個無限迴圈 。可以用其他方式終止迴圈, 如一條 break return
句。

// a traditional infinite loop
for {
// ...
}

2)for 迴圈的第二種形式
在某種資料型別的區間( range) 上遍歷, 如字串或切片。 echo 的第二版本展示了這種形式:

// Echo2 prints its command-line arguments.
package main

import (
    "fmt"
    "os"
) 

func main() {
    s, sep := "", ""
    for _, arg := range os.Args[1:] {
        s += sep + arg
        sep = " "
    }
    fmt.Println(s)
}

每次迴圈迭代, range 產生一對值; 索引以及在該索引處的元素值。 這個例子不需要索引,但 range 的語法要求, 要處理元素, 必須處理索引。 一種思路是把索引賦值給一個臨時變數,temp , 然後忽略它的值, 但Go語言不允許使用無用的區域性變數( local variables) , 因為這
會導致編譯錯誤。 Go語言中這種情況的解決方法是用 空標識blank identifier) , 即 _ ( 也就是下劃線) 。空識別符號可用於任何語法需要變數名但程式邏輯不需要的時候。
宣告一個變數有好幾種方式, 下面這些都等價:

s := ""
var s string
var s = ""
var s string = ""

第一種形式, 是一條短變數宣告, 最簡潔, 但只能用在函式內部, 而不能用於包變數。

第二種形式依賴於字串的預設初始化零值機制, 被初始化為""

三種形式用得很少, 除非同時宣告多個變數。

第四種形式顯式地標明變數的型別, 當變數類 型與初值型別相同時, 型別冗餘, 但如果兩者型別不同, 變數型別就必須了。 實踐中一般使用前兩種形式中的某個, 初始值重要的話就顯式地指定變數的型別, 否則使用隱式初始化。

上面實現的echo程式 每次迴圈都會更新 s 如果連線涉及的資料量很大, 這種方式代價高昂。 一種簡單且高效的解決方案是使用 strings 包的 Join 函式

func main() {
    fmt.Println(strings.Join(os.Args[1:], " "))
}

3. 查詢重複的行