## 4.5\. Echo
下面的例子是Unix系統中"echo"命令的簡單實現:
```
05 package main
07 import (
08 "os"
09 "flag" // command line option parser
10 )
12 var omitNewline = flag.Bool("n", false, "don't print final newline")
14 const (
15 Space = " "
16 Newline = "\n"
17 )
19 func main() {
20 flag.Parse() // Scans the arg list and sets up flags
21 var s string = ""
22 for i := 0; i < flag.NArg(); i++ {
23 if i > 0 {
24 s += Space
25 }
26 s += flag.Arg(i)
27 }
28 if !*omitNewline {
29 s += Newline
30 }
31 os.Stdout.WriteString(s)
32 }
```
程序雖然很小,但是包含了go語言的更多特性。在上一個的例子中,我們演示了如何用"func"關鍵字定義函數。 類似的關鍵字還有:"var"、"const"和"type"等,它們可以用于定義變量、常量和類型等,用法和"import"一致。 我們可以小括弧聲明一組類型相同的變量(如7-10和14-17行所示)。當然,也可以分開獨立定義:
```
const Space = " "
const Newline = "\n"
```
程序首先導入 os 包,因為后面要用到包中的一個 *os.File 類型的 Stdout 變量。 這里的 import 語句實際上是一個聲明,和我們在 hello world 程序中所使用方法一樣,包的名字標識符(fmt) 為前綴用于定位包中定位包中的成員,包可以是在當前目錄或標準包目錄。在導入包的時候一般會默認選用包本身的 名字(在必要的時候可以將導入的包重新命名)。在“hello world”程序中,我們只是簡單的 import "fmt" 。
如果需要,你可以自己重新命名被import的包。但那不是必須的,只在處理包名字沖突的時候會用到。
通過"os.Stdout",我們可以用包中的"WriteString?"方法來輸出字符串。
現在已經導入"flag"包,并且在12行創建了一個全局變量,用于保存echo的"-n"命令行選項。變量 "omitNewline"為一個只想bool變量的bool型指針。
在"main.main"中,我們首先解析命令行參數(20行),然后創建了一個局部字符串變量用于保存要輸出的內容。
變量聲明語法如下:
```
var s string = "";
```
這里有一個"var"關鍵字,后面跟著變量名字和變量的數據類型,再后面可以用“=”符號來進行賦初值。
簡潔是go的一個目標,變量的定義也有更簡略的語法。go可以根據初始值來判斷變量的類型, 沒有必要顯式寫出數據類型。也可以這樣定義變量:
```
var s = "";
```
還有更短的寫法:
s := ""; 操作符":="將在Go中聲明同時進行初始化一個變量時會經常使用。下面的代碼是在"for"中聲明并 初始化變量:
```
22 for i := 0; i < flag.NArg(); i++ {
```
"flag"包會解析命令行參數,并將不是flag選項的參數保存到一個列表中。可以通過flag的參數列表 訪問普通的命令行參數。
Go語言的"for"語句和C語言中有幾個不同的地方:第一,for是Go中唯一的循環語句,Go中沒有while或 do語句;第二,for的條件語句并不需要用小括號包起來,但是循環體卻必須要花括弧,這個規則同樣適用于 if和switch。后面我們會看到for的一些例子。
在循環體中,通過"+="操作符向字符串"s"添加要命令行參數和空白。在循環結束后,根據命令行是否有"-n"選項, 判斷末尾是否要添加換行符。最后輸出結果。
值得注意的地方是"main.main"函數并沒有返回值(函數被定義為沒有返回值的類型)。如果"main.main" 運行到了末尾,就表示“成功”。如果想返回一個出錯信息,可用系統調用強制退出:
```
os.Exit(1)
```
"os"包還包含了其它的許多啟動相關的功能,例如"os.Args"是"flag"包的一部分(用來獲取命令行輸入)。
- 1. 關于本文
- 2. Go語言簡介
- 3. 安裝go環境
- 3.1. 簡介
- 3.2. 安裝C語言工具
- 3.3. 安裝Mercurial
- 3.4. 獲取代碼
- 3.5. 安裝Go
- 3.6. 編寫程序
- 3.7. 進一步學習
- 3.8. 更新go到新版本
- 3.9. 社區資源
- 3.10. 環境變量
- 4. Go語言入門
- 4.1. 簡介
- 4.2. Hello,世界
- 4.3. 分號(Semicolons)
- 4.4. 編譯
- 4.5. Echo
- 4.6. 類型簡介
- 4.7. 申請內存
- 4.8. 常量
- 4.9. I/O包
- 4.10. Rotting cats
- 4.11. Sorting
- 4.12. 打印輸出
- 4.13. 生成素數
- 4.14. Multiplexing
- 5. Effective Go
- 5.1. 簡介
- 5.2. 格式化
- 5.3. 注釋
- 5.4. 命名
- 5.5. 分號
- 5.6. 控制流
- 5.7. 函數
- 5.8. 數據
- 5.9. 初始化
- 5.10. 方法
- 5.11. 接口和其他類型
- 5.12. 內置
- 5.13. 并發
- 5.14. 錯誤處理
- 5.15. Web服務器
- 6. 如何編寫Go程序
- 6.1. 簡介
- 6.2. 社區資源
- 6.3. 新建一個包
- 6.4. 測試
- 6.5. 一個帶測試的演示包
- 7. Codelab: 編寫Web程序
- 7.1. 簡介
- 7.2. 開始
- 7.3. 數據結構
- 7.4. 使用http包
- 7.5. 基于http提供wiki頁面
- 7.6. 編輯頁面
- 7.7. template包
- 7.8. 處理不存在的頁面
- 7.9. 儲存頁面
- 7.10. 錯誤處理
- 7.11. 模板緩存
- 7.12. 驗證
- 7.13. 函數文本和閉包
- 7.14. 試試!
- 7.15. 其他任務
- 8. 針對C++程序員指南
- 8.1. 概念差異
- 8.2. 語法
- 8.3. 常量
- 8.4. Slices(切片)
- 8.5. 構造值對象
- 8.6. Interfaces(接口)
- 8.7. Goroutines
- 8.8. Channels(管道)
- 9. 內存模型
- 9.1. 簡介
- 9.2. Happens Before
- 9.3. 同步(Synchronization)
- 9.4. 錯誤的同步方式
- 10. 附錄
- 10.1. 命令行工具
- 10.2. 視頻和講座
- 10.3. Release History
- 10.4. Go Roadmap
- 10.5. 相關資源