本節將通過Hello World帶領大家進入Go的世界,並由此介紹Go代碼的主要結構、部分關鍵字和包的一些特性。爲閱讀後面的打下基礎。
1. Let's go
咱們以往學習任何程序都會以Hello World作爲第一個實例,在此咱們不按常理出牌,針對Go語言,我們的第一個程序以Let's go開始。(其實是換湯不換藥哈!!)。
代碼如下:
控制檯的輸出結果爲:Let's go!
- 第2行:定義此代碼所屬的包名,在一個項目中有且只有一個名爲main的包。(最佳實踐:包名由簡短且小寫的字母構成)
- 包名爲源代碼文件所屬的目錄名。即同一包的所有的代碼文件必須放在以此包名爲目錄名的目錄下。
- 在包的定義聲明中只能有一個包名,這與Java、C#是不一樣的(注:在Java中的包定義是從根依次引入的)
- 第5~7行:定義此代碼所依賴的其它包。(關鍵字import等同於Java中的import)
- 可以引入多個包,並支持放在同一行,彼此之間以逗號“,”分隔。
- 最佳實踐:包的引入按標準庫包,自定義包,第三方包的順序定義
- 第10行:爲程序的入口函數,類似於C,Java中的main方法。
- 第12行:調用標準庫fmt中的Println函數將字符串輸出到標準輸出設備上。
- 此庫中還有幾個類型的函數,如:Printf(), Fprint()等。
- 在Go的註釋方式支持兩種,與C,Java相同。
- 單行的註釋://
- 多行的註釋:/* */
- 在包定義、包引入、全局變量/常量、函數定義上面的註釋可以用godoc來查看或生成說明文檔(注:註釋與聲明間不能有空行)
- Go爲了減少編碼的輸入,讓代碼更簡潔。它允許每一行的最後可以省略分號“;"。
- 最後編譯鏈接後生成一個可執行二事制文件,如在Windows平臺上爲.exe文件。(注:此文件中包含了Go的運行時環境 -- 這使發佈此程序變量的簡單,不需要客戶機上單獨安裝運行環境)
2. 包的特點
包即是Go中組織源代碼的一種結構,每一個go源碼文件只能屬於一個包(即存放於此包對應的目錄下),但一個包可以包括多個go源碼文件(但這些文件不能有同名)。(注:包的字名需要有小寫字符)
在編譯時,包中的所有文件需要一起編譯,並最終生成一個擴展爲.a的文件,如pack1.a。
Go標準庫所處的目錄因環境不同而有所差異:
- 通用的標準是:$GOROOT\pkg\$GOOS_$GOARCH
- Windows:$GOROOT\pkg\windows_386
- Linux:$GORROT\pkg\linux_amd32/64
包的依賴引用需顯示的說明其依賴關係,由此加快編譯速度。當一個包改變或重新編譯後,所有的依賴於它的代碼都將被重新編譯。
假設這裏有三個文件:a.go依賴於b.go,b.go依賴於c.go:
- 編譯順序爲:c.go -> b.go -> a.go
- 當只編譯a.go時,編譯器只需讀取b.o文件,而不需要c.o。
當使用import引用包時,需注意它的搜索路徑:
- 當沒有以/開始時(如"fmt","container/list"),Go編譯器會到Go的標準庫中搜索此包。
- 當以./開始時,則從當前路徑爲起始目錄開始搜索。
- 當以/開始時,則從系統的根目錄開始搜索。
3. 包引用的可見規則
在Go中對包中定義的各種標識(常量、變量、函數、類型等)的可見性只有兩種:
- 以大寫字母開始的標識,在包外可見。即當使用import引用包時,這些標準可以在客戶代碼中直接調用(引用)。也就相當於Java中以Public關鍵字修飾的標識。
- 以小字字母開始的標識,在整個包內可見,即可以在包內的多個文件中可見。相當於Java中用private修飾的標識。
- 包相關於命名空間,不同包下相同名字並不衝突,並在某些特定情況可以在import包時,指定別名來在避免衝突。
4. 實例代碼
本例主要展示自定包義的組織結構、包中各代碼文件的關係、代碼中各種標識符的可見性和包的引用。代碼結構如下所示:
- 新創建一個名爲chapter3的包,其中包括兩個代碼文件(demo1.go和demo2.go)和子包inner。
- 子包inner中包含一個代碼文件:innerpack.go。
各代碼塊如下:
- main包及入口函數
- demo1.go
- demo2.go
- inner包中的innerpack.go
- 輸出結果爲:
總結:
- 在客戶代碼中導入自定義包時,一般是通過相對路徑來指定,而對於導入標準庫時,則是直接以包名開始。 如本例的demo1.go的第4,5行:
- 第4行:導入的是自定包,位於子目錄inner中。
- 第5行:導入標準庫的包,則直接以包名開始,以映射到$GOROOT\pkg\windows_386\。
- 包的導入順序:首先是自定義包,再是標準包。
- 同包中的多個代碼文件彼此間的全局變量、函數等都是相互可見的。
- 如在demo1.go中可以直接調用demo2.go中的以小寫字母開頭的方法。
- 如在demo2.go中可以直接調用demo1.go中的以小寫字母開頭的變量。
- 以大寫字母開頭的常量、變量和函數等在包外是可見的。
- 每個包編譯後都會生成一個以包名相同的擴展爲.a的庫文件。
- 在同一包中的多個文件中不能有同名的變量、常量、函數等。需保證在包內唯一。