diff --git a/eBook/04.7.md b/eBook/04.7.md index 2e7401c..db2f347 100644 --- a/eBook/04.7.md +++ b/eBook/04.7.md @@ -273,7 +273,7 @@ func main() { GO1 - The ABC of Go - 25 - sl2 joined by ;: GO1;The ABC of Go;25 -其它有关字符串操作的文档请参阅官方文档 [http://golang.org/pkg/strings/](http://golang.org/pkg/strings/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/strings/)** )。 +其它有关字符串操作的文档请参阅 [官方文档](http://golang.org/pkg/strings/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/strings/)** )。 ## 4.7.11 从字符串中读取内容 @@ -341,7 +341,7 @@ func main() { 在第 5.1 节,我们将会利用 if 语句来对可能出现的错误进行分类处理。 -更多有关该包的讨论,请参阅官方文档 [http://golang.org/pkg/strconv/](http://golang.org/pkg/strconv/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/strconv/)** )。 +更多有关该包的讨论,请参阅 [官方文档](http://golang.org/pkg/strconv/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/strconv/)** )。 ## 链接 diff --git a/eBook/04.8.md b/eBook/04.8.md index 7b7eae3..7b32667 100644 --- a/eBook/04.8.md +++ b/eBook/04.8.md @@ -9,44 +9,48 @@ Duration 类型表示两个连续时刻所相差的纳秒数,类型为 int64 包中的一个预定义函数 `func (t Time) Format(layout string) string` 可以根据一个格式化字符串来将一个时间 t 转换为相应格式的字符串,你可以使用一些预定义的格式,如:`time.ANSIC` 或 `time.RFC822`。 一般的格式化设计是通过对于一个标准时间的格式化描述来展现的,这听起来很奇怪,但看下面这个例子你就会一目了然: - - fmt.Println(t.Format("02 Jan 2006 15:04")) + +```go +fmt.Println(t.Format("02 Jan 2006 15:04")) +``` 输出: 21 Jul 2011 10:31 -其它有关时间操作的文档请参阅官方文档 [http://golang.org/pkg/time/](http://golang.org/pkg/time/)( **译者注:国内用户可访问 [http://docs.studygolang.com/pkg/time/](http://docs.studygolang.com/pkg/time/)** )。 +其它有关时间操作的文档请参阅 [官方文档](http://golang.org/pkg/time/)( **译者注:国内用户可访问 [该页面](http://docs.studygolang.com/pkg/time/)** )。 -Example 4.20 [time.go](examples/chapter_4/time.go) +示例 4.20 [time.go](examples/chapter_4/time.go) + +```go +package main +import ( + "fmt" + "time" +) - package main - import ( - "fmt" - "time" - ) - - var week time.Duration - func main() { - t := time.Now() - fmt.Println(t) // e.g. Wed Dec 21 09:52:14 +0100 RST 2011 - fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year()) - // 21.12.2011 - t = time.Now().UTC() - fmt.Println(t) // Wed Dec 21 08:52:14 +0000 UTC 2011 - fmt.Println(time.Now()) // Wed Dec 21 09:52:14 +0100 RST 2011 - // calculating times: - week = 60 * 60 * 24 * 7 * 1e9 // must be in nanosec - week_from_now := t.Add(week) - fmt.Println(week_from_now) // Wed Dec 28 08:52:14 +0000 UTC 2011 - // formatting times: - fmt.Println(t.Format(time.RFC822)) // 21 Dec 11 0852 UTC - fmt.Println(t.Format(time.ANSIC)) // Wed Dec 21 08:56:34 2011 - fmt.Println(t.Format("02 Jan 2006 15:04")) // 21 Dec 2011 08:52 - s := t.Format("20060102") - fmt.Println(t, "=>", s) - // Wed Dec 21 08:52:14 +0000 UTC 2011 => 20111221 - } +var week time.Duration +func main() { + t := time.Now() + fmt.Println(t) // e.g. Wed Dec 21 09:52:14 +0100 RST 2011 + fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year()) + // 21.12.2011 + t = time.Now().UTC() + fmt.Println(t) // Wed Dec 21 08:52:14 +0000 UTC 2011 + fmt.Println(time.Now()) // Wed Dec 21 09:52:14 +0100 RST 2011 + // calculating times: + week = 60 * 60 * 24 * 7 * 1e9 // must be in nanosec + week_from_now := t.Add(week) + fmt.Println(week_from_now) // Wed Dec 28 08:52:14 +0000 UTC 2011 + // formatting times: + fmt.Println(t.Format(time.RFC822)) // 21 Dec 11 0852 UTC + fmt.Println(t.Format(time.ANSIC)) // Wed Dec 21 08:56:34 2011 + fmt.Println(t.Format("02 Jan 2006 15:04")) // 21 Dec 2011 08:52 + s := t.Format("20060102") + fmt.Println(t, "=>", s) + // Wed Dec 21 08:52:14 +0000 UTC 2011 => 20111221 +} +``` 输出的结果已经写在每行 `//` 的后面。 diff --git a/eBook/04.9.md b/eBook/04.9.md index bda2fc8..32c95c2 100644 --- a/eBook/04.9.md +++ b/eBook/04.9.md @@ -8,14 +8,18 @@ Go 语言的取地址符是 `&`,放到一个变量前使用就会返回相应变量的内存地址。 -下面的代码片段(Example 4.9 [pointer.go](examples/chapter_4/pointer.go))可能输出 `An integer: 5, its location in memory: 0x6b0820`(这个值随着你每次运行程序而变化)。 - - var i1 = 5 - fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1) +下面的代码片段(示例 4.9 [pointer.go](examples/chapter_4/pointer.go))可能输出 `An integer: 5, its location in memory: 0x6b0820`(这个值随着你每次运行程序而变化)。 + +```go +var i1 = 5 +fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1) +``` 这个地址可以存储在一个叫做指针的特殊数据类型中,在本例中这是一个指向 int 的指针,即 `i1`:此处使用 *int 表示。如果我们想调用指针 intP,我们可以这样声明它: - - var intP *int + +```go +var intP *int +``` 然后使用 `intP = &i1` 是合法的,此时 intP 指向 i1。 @@ -39,20 +43,22 @@ intP 存储了 i1 的内存地址;它指向了 i1 的位置,它引用了变 现在,我们应当能理解 pointer.go 中的整个程序和他的输出: -Example 4.21 [pointer.go](examples/chapter_4/pointer.go): - - package main - import "fmt" - func main() { - var i1 = 5 - fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1) - var intP *int - intP = &i1 - fmt.Printf("The value at memory location %p is %d\n", intP, *intP) - } +示例 4.21 [pointer.go](examples/chapter_4/pointer.go): + +```go +package main +import "fmt" +func main() { + var i1 = 5 + fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1) + var intP *int + intP = &i1 + fmt.Printf("The value at memory location %p is %d\n", intP, *intP) +} +``` 输出: - + An integer: 5, its location in memory: 0x24f0820 The value at memory location 0x24f0820 is 5 @@ -64,18 +70,20 @@ Example 4.21 [pointer.go](examples/chapter_4/pointer.go): 它展示了分配一个新的值给 *p 并且更改这个变量自己的值(这里是一个字符串)。 -Example 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go) - - package main - import "fmt" - func main() { - s := "good bye" - var p *string = &s - *p = "ciao" - fmt.Printf("Here is the pointer p: %p\n", p) // prints address - fmt.Printf("Here is the string *p: %s\n", *p) // prints string - fmt.Printf("Here is the string s: %s\n", s) // prints same string - } +示例 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go) + +```go +package main +import "fmt" +func main() { + s := "good bye" + var p *string = &s + *p = "ciao" + fmt.Printf("Here is the pointer p: %p\n", p) // prints address + fmt.Printf("Here is the string *p: %s\n", *p) // prints string + fmt.Printf("Here is the string s: %s\n", s) // prints same string +} +``` 输出: @@ -92,10 +100,12 @@ Example 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go) **注意事项** 你不能得到一个文字或常量的地址,例如: - - const i = 5 - ptr := &i //error: cannot take the address of i - ptr2 := &10 //error: cannot take the address of 10 + +```go +const i = 5 +ptr := &i //error: cannot take the address of i +ptr2 := &10 //error: cannot take the address of 10 +``` 所以说,Go 语言和 C、C++ 以及 D 语言这些低级(系统)语言一样,都有指针的概念。但是对于经常导致 C 语言内存泄漏继而程序崩溃的指针运算(所谓的指针算法,如:`pointer+2`,移动指针指向字符串的字节数或数组的某个位置)是不被允许的。Go 语言中的指针保证了内存安全,更像是 Java、C# 和 VB.NET 中的引用。 @@ -111,15 +121,17 @@ Example 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go) 对一个空指针的反向引用是不合法的,并且会使程序崩溃: -Example 4.23 [testcrash.go](examples/chapter_4/testcrash.go): - - package main - func main() { - var p *int = nil - *p = 0 - } - // in Windows: stops only with: - // runtime error: invalid memory address or nil pointer dereference +示例 4.23 [testcrash.go](examples/chapter_4/testcrash.go): + +```go +package main +func main() { + var p *int = nil + *p = 0 +} +// in Windows: stops only with: +// runtime error: invalid memory address or nil pointer dereference +``` **问题 4.2** 列举 Go 语言中 * 号的所有用法。 diff --git a/eBook/05.0.md b/eBook/05.0.md index c27fb45..67f9826 100644 --- a/eBook/05.0.md +++ b/eBook/05.0.md @@ -2,13 +2,13 @@ 到目前为止,我们看到的都是 Go 程序都是从 main() 函数开始执行,然后按顺序执行该函数体中的代码。但我们经常会需要只有在满足一些特定情况时才执行某些代码,也就是说在代码里进行条件判断。针对这种需求,Go 提供了下面这些条件结构和分支结构: - if-else 结构 - switch 结构 - select 结构,用于 channel 的选择(第 14.4 节) +- if-else 结构 +- switch 结构 +- elect 结构,用于 channel 的选择(第 14.4 节) 可以使用迭代或循环结构来重复执行一次或多次某段代码(任务): - for (range) 结构 +- for (range) 结构 一些如 `break` 和 `continue` 这样的关键字可以用于中途改变循环的状态。 diff --git a/eBook/05.1.md b/eBook/05.1.md index 5ac70db..e6c1eae 100644 --- a/eBook/05.1.md +++ b/eBook/05.1.md @@ -2,27 +2,33 @@ if 是用于测试某个条件(布尔型或逻辑型)的语句,如果该条件成立,则会执行 if 后由大括号括起来的代码块,否则就忽略该代码块继续执行后续的代码。 - if condition { - // do something - } +```go +if condition { + // do something +} +``` 如果存在第二个分支,则可以在上面代码的基础上添加 else 关键字以及另一代码块,这个代码块中的代码只有在条件不满足时才会执行。if 和 else 后的两个代码块是相互独立的分支,只可能执行其中一个。 - if condition { - // do something - } else { - // do something - } +```go +if condition { + // do something +} else { + // do something +} +``` 如果存在第三个分支,则可以使用下面这种三个独立分支的形式: - if condition1 { - // do something - } else if condition2 { - // do something else - }else { - // catch-all or default - } +```go +if condition1 { + // do something +} else if condition2 { + // do something else +}else { + // catch-all or default +} +``` else-if 分支的数量是没有限制的,但是为了代码的可读性,还是不要在 if 后面加入太多的 else-if 结构。如果你必须使用这种形式,则把尽可能先满足的条件放在前面。 @@ -32,10 +38,12 @@ else-if 分支的数量是没有限制的,但是为了代码的可读性,还 非法的Go代码: - if x{ - } - else { // 无效的 - } +```go +if x{ +} +else { // 无效的 +} +``` 要注意的是,在你使用 `gofmt` 格式化代码之后,每个分支内的代码都会缩进 4 个或 8 个空格,或者是 1 个 tab,并且右大括号与对应的 if 关键字垂直对齐。 @@ -43,18 +51,20 @@ else-if 分支的数量是没有限制的,但是为了代码的可读性,还 一种可能用到条件语句的场景是测试变量的值,在不同的情况执行不同的语句,不过将在第 5.3 节讲到的 switch 结构会更适合这种情况。 -Example 5.1 [booleans.go](examples/chapter_5/booleans.go) +示例 5.1 [booleans.go](examples/chapter_5/booleans.go) - package main - import "fmt" - func main() { - bool1 := true - if bool1 { - fmt.Printf("The value is true\n") - } else { - fmt.Printf("The value is false\n") - } +```go +package main +import "fmt" +func main() { + bool1 := true + if bool1 { + fmt.Printf("The value is true\n") + } else { + fmt.Printf("The value is false\n") } +} +``` 输出: @@ -66,22 +76,26 @@ Example 5.1 [booleans.go](examples/chapter_5/booleans.go) 当 if 结构内有 break、continue、goto 或者 return 语句时,Go 代码的常见写法是省略 else 部分(另见第 5.2 节)。无论满足哪个条件都会返回 x 或者 y 时,一般使用以下写法: - if condition { - return x - } - return y +```go +if condition { + return x +} +return y +``` -**注意事项** 不要同时在 if-else 结构的两个分支里都使用 return 语句,这将导致编译报错 “function ends without a return statement”(你可以认为这是一个编译器的 Bug 或者特性)。( **译者注:该问题已经在 Go 1.1 中被修复或者说改进** ) +**注意事项** 不要同时在 if-else 结构的两个分支里都使用 return 语句,这将导致编译报错 `function ends without a return statement`(你可以认为这是一个编译器的 Bug 或者特性)。( **译者注:该问题已经在 Go 1.1 中被修复或者说改进** ) 这里举一些有用的例子: -1. 判断一个字符串是否为空:`if str == "" { ... }` 或 `if len(str) == 0 {...}`。 +1. 判断一个字符串是否为空: + - `if str == "" { ... }` + - `if len(str) == 0 {...}` 2. 判断运行 Go 程序的操作系统类型,这可以通过常量 `runtime.GOOS` 来判断(第 2.2 节)。 - - if runtime.GOOS == "windows" { - ... - } else { // Unix - like - ... + + if runtime.GOOS == "windows" { + . .. + } else { // Unix - li ke + . .. } 这段代码一般被放在 init() 函数中执行。这儿还有一段示例来演示如何根据操作系统来决定输入结束的提示: @@ -116,53 +130,61 @@ Example 5.1 [booleans.go](examples/chapter_5/booleans.go) 在第四种情况中,if 可以包含一个初始化语句(如:给一个变量赋值)。这种写法具有固定的格式(在初始化语句后方必须加上分号): - if initialization; condition { - // do something - } +```go +if initialization; condition { + // do something +} +``` 例如: - val := 10 - if val > max { - // do something - } +```go +val := 10 +if val > max { + // do something +} +``` 你也可以这样写: - if val := 10; val > max { - // do something - } +```go +if val := 10; val > max { + // do something +} +``` 但要注意的是,使用简短方式 `:=` 声明的变量的作用域只存在于 if 结构中(在 if 结构的大括号之间,如果使用 if-else 结构则在 else 代码块中变量也会存在)。如果变量在 if 结构之前就已经存在,那么在 if 结构中,该变量原来的值会被隐藏。最简单的解决方案就是不要在初始化语句中声明变量(见 5.2 节的例 3 了解更多)。 -Example 5.2 [ifelse.go](examples/chapter_5/ifelse.go) +示例 5.2 [ifelse.go](examples/chapter_5/ifelse.go) - package main - - import "fmt" - - func main() { - var first int = 10 - var cond int - - if first <= 0 { - - fmt.Printf("first is less than or equal to 0\n") - } else if first > 0 && first < 5 { - - fmt.Printf("first is between 0 and 5\n") - } else { - - fmt.Printf("first is 5 or greater\n") - } - if cond = 5; cond > 10 { - - fmt.Printf("cond is greater than 10\n") - } else { - - fmt.Printf("cond is not greater than 10\n") - } +```go +package main + +import "fmt" + +func main() { + var first int = 10 + var cond int + + if first <= 0 { + + fmt.Printf("first is less than or equal to 0\n") + } else if first > 0 && first < 5 { + + fmt.Printf("first is between 0 and 5\n") + } else { + + fmt.Printf("first is 5 or greater\n") } + if cond = 5; cond > 10 { + + fmt.Printf("cond is greater than 10\n") + } else { + + fmt.Printf("cond is not greater than 10\n") + } +} +``` 输出: @@ -170,11 +192,13 @@ Example 5.2 [ifelse.go](examples/chapter_5/ifelse.go) 下面的代码片段展示了如何通过在初始化语句中获取函数 `process()` 的返回值,并在条件语句中作为判定条件来决定是否执行 if 结构中的代码: - if value := process(data); value > max { - ... - if value := process(data); value > max { - ... - } +```go +if value := process(data); value > max { + ... +if value := process(data); value > max { + ... +} +``` ## 链接