This commit is contained in:
Unknown
2014-04-09 00:04:59 -04:00
parent f66ca15956
commit 480ec9f46a
10 changed files with 114 additions and 62 deletions

View File

@@ -9,7 +9,7 @@
## 翻译进度 ## 翻译进度
3.9 [与其它语言进行交互](eBook/03.9.md) 4.9 [指针](eBook/04.9.md)
## 支持本书 ## 支持本书

View File

@@ -1,4 +1,5 @@
#4.1 文件名、关键字与标识符 # 4.1 文件名、关键字与标识符
Go 的源文件以 `.go` 为后缀名存储在计算机中,这些文件名均由小写字母组成,如 `scanner.go` 。如果文件名由多个部分组成,则使用下划线 `_` 对它们进行分隔,如 `scanner_test.go` 。文件名不包含空格或其他特殊字符。 Go 的源文件以 `.go` 为后缀名存储在计算机中,这些文件名均由小写字母组成,如 `scanner.go` 。如果文件名由多个部分组成,则使用下划线 `_` 对它们进行分隔,如 `scanner_test.go` 。文件名不包含空格或其他特殊字符。
一个源文件可以包含任意多行的代码Go 本身没有对源文件的大小进行限制。 一个源文件可以包含任意多行的代码Go 本身没有对源文件的大小进行限制。
@@ -114,7 +115,8 @@ Go 的源文件以 `.go` 为后缀名存储在计算机中,这些文件名均
如果你打算将多个语句写在同一行,它们则必须使用 `;` 人为区分,但在实际开发中我们并不鼓励这种做法。 如果你打算将多个语句写在同一行,它们则必须使用 `;` 人为区分,但在实际开发中我们并不鼓励这种做法。
##链接 ## 链接
- [目录](directory.md) - [目录](directory.md)
- 上一部分:[与其它语言进行交互](03.9.md) - 上一部分:[与其它语言进行交互](03.9.md)
- 下一节:[Go 程序的基本结构和要素](04.2.md) - 下一节:[Go 程序的基本结构和要素](04.2.md)

View File

@@ -1,4 +1,5 @@
#4.2 Go 程序的基本结构和要素 # 4.2 Go 程序的基本结构和要素
Example 4.1 [hello_world.go](examples/chapter_4/hello_world.go) Example 4.1 [hello_world.go](examples/chapter_4/hello_world.go)
package main package main
@@ -9,7 +10,8 @@ Example 4.1 [hello_world.go](examples/chapter_4/hello_world.go)
fmt.Println("hello, world") fmt.Println("hello, world")
} }
##4.2.1 包的概念、导入与可见性 ## 4.2.1 包的概念、导入与可见性
包是结构化代码的一种方式:每个程序都由包(通常简称为 pkg的概念组成可以使用自身的包或者从其它包中导入内容。 包是结构化代码的一种方式:每个程序都由包(通常简称为 pkg的概念组成可以使用自身的包或者从其它包中导入内容。
如同其它一些编程语言中的类库或命名空间的概念,每个 Go 文件都属于且仅属于一个包。一个包可以由许多以 `.go` 为扩展名的源文件组成,因此文件名和包名一般来说都是不相同的。 如同其它一些编程语言中的类库或命名空间的概念,每个 Go 文件都属于且仅属于一个包。一个包可以由许多以 `.go` 为扩展名的源文件组成,因此文件名和包名一般来说都是不相同的。
@@ -52,7 +54,7 @@ Go 中的包模型采用了显式依赖关系的机制来达到快速编译的
或: 或:
import fmt; import os import "fmt"; import "os"
但是还有更短且更优雅的方法(被称为因式分解关键字,该方法同样适用于 const、var 和 type 的声明或定义): 但是还有更短且更优雅的方法(被称为因式分解关键字,该方法同样适用于 const、var 和 type 的声明或定义):
@@ -102,7 +104,8 @@ Example 4.2 [alias.go](examples/chapter_4/alias.go)
你可以在使用 `import` 导入包之后定义或声明 0 个或多个常量const、变量var和类型type这些对象的作用域都是全局的在本包范围内所以可以被本包中所有的函数调用如 [gotemplate.go](examples/chapter_4/gotemplate.go) 源文件中的 c 和 v然后声明一个或多个函数func 你可以在使用 `import` 导入包之后定义或声明 0 个或多个常量const、变量var和类型type这些对象的作用域都是全局的在本包范围内所以可以被本包中所有的函数调用如 [gotemplate.go](examples/chapter_4/gotemplate.go) 源文件中的 c 和 v然后声明一个或多个函数func
##4.2.2 函数 ## 4.2.2 函数
这是定义一个函数最简单的格式:`func functionName()` 这是定义一个函数最简单的格式:`func functionName()`
你可以在括号 `()` 中写入 0 个或多个函数的参数(使用逗号 `,` 分隔),每个参数的名称后面必须紧跟着该参数的类型。 你可以在括号 `()` 中写入 0 个或多个函数的参数(使用逗号 `,` 分隔),每个参数的名称后面必须紧跟着该参数的类型。
@@ -151,7 +154,8 @@ main 函数是每一个可执行程序所必须包含的,一般来说都是在
程序正常退出的代码为 0 `Program exited with code 0`如果程序因为异常而被终止则会返回非零值1。这个数值可以用来测试是否成功执行一个程序。 程序正常退出的代码为 0 `Program exited with code 0`如果程序因为异常而被终止则会返回非零值1。这个数值可以用来测试是否成功执行一个程序。
##4.2.3 注释 ## 4.2.3 注释
Example 4.2 [hello_world2.go](examples/chapter_4/hello_world2.go) Example 4.2 [hello_world2.go](examples/chapter_4/hello_world2.go)
package main package main
@@ -188,7 +192,8 @@ Example 4.2 [hello_world2.go](examples/chapter_4/hello_world2.go)
godoc 工具(第 3.6 节)会收集这些注释并产生一个技术文档。 godoc 工具(第 3.6 节)会收集这些注释并产生一个技术文档。
##4.2.4 类型 ## 4.2.4 类型
可以包含数据的变量(或常量)可以使用不同的数据类型或类型来保存数据。使用 var 声明的变量的值会自动初始化为该类型的零值。类型定义了某个变量的值的集合与可对其进行操作的集合。 可以包含数据的变量(或常量)可以使用不同的数据类型或类型来保存数据。使用 var 声明的变量的值会自动初始化为该类型的零值。类型定义了某个变量的值的集合与可对其进行操作的集合。
类型可以是基本类型intfloatboolstring结构化的复合的structarrayslicemapchannel只描述类型的行为的interface。 类型可以是基本类型intfloatboolstring结构化的复合的structarrayslicemapchannel只描述类型的行为的interface。
@@ -215,7 +220,7 @@ godoc 工具(第 3.6 节)会收集这些注释并产生一个技术文档。
type IZ int type IZ int
***译者注:这里并不是真正意义上的别名,因为使用这种方法定义之后的类型可以拥有更多的特性,且在类型转换时必须显式转换*** **译者注:这里并不是真正意义上的别名,因为使用这种方法定义之后的类型可以拥有更多的特性,且在类型转换时必须显式转换**
然后我们可以像 `var a IZ = 5` 这样声明变量。 然后我们可以像 `var a IZ = 5` 这样声明变量。
@@ -231,7 +236,8 @@ godoc 工具(第 3.6 节)会收集这些注释并产生一个技术文档。
每个值都必须在经过编译后属于某个类型(编译器必须能够推断出所有值的类型),因为 Go 语言是一种静态类型语言。 每个值都必须在经过编译后属于某个类型(编译器必须能够推断出所有值的类型),因为 Go 语言是一种静态类型语言。
##4.2.5 Go 程序的一般结构 ## 4.2.5 Go 程序的一般结构
下面的程序可以被顺利编译但什么都做不了,不过这很好地展示了一个 Go 程序的首选结构。这种结构并没有被强制要求,编译器也不关心 main 函数在前还是变量的声明在前,但使用统一的结构能够在从上至下阅读 Go 代码时有更好的体验。 下面的程序可以被顺利编译但什么都做不了,不过这很好地展示了一个 Go 程序的首选结构。这种结构并没有被强制要求,编译器也不关心 main 函数在前还是变量的声明在前,但使用统一的结构能够在从上至下阅读 Go 代码时有更好的体验。
所有的结构将在这一章或接下来的章节中进一步地解释说明,但总体思路如下: 所有的结构将在这一章或接下来的章节中进一步地解释说明,但总体思路如下:
@@ -272,12 +278,13 @@ Go 程序的执行(程序启动)顺序如下:
3. 然后以相反的顺序在每个包中初始化常量和变量,如果该包含有 init 函数的话,则调用该函数。 3. 然后以相反的顺序在每个包中初始化常量和变量,如果该包含有 init 函数的话,则调用该函数。
4. 在完成这一切之后main 也执行同样的过程,最后调用 main 函数开始执行程序。 4. 在完成这一切之后main 也执行同样的过程,最后调用 main 函数开始执行程序。
##4.2.6 类型转换 ## 4.2.6 类型转换
在必要以及可行的情况下,一个类型的值可以被转换成另一种类型的值。由于 Go 语言不存在隐式类型转换,因此所有的转换都必须显式说明,就像调用一个函数一样(类型在这里的作用可以看作是一种函数): 在必要以及可行的情况下,一个类型的值可以被转换成另一种类型的值。由于 Go 语言不存在隐式类型转换,因此所有的转换都必须显式说明,就像调用一个函数一样(类型在这里的作用可以看作是一种函数):
valueOfTypeB = typeB(valueOfTypeA) valueOfTypeB = typeB(valueOfTypeA)
***译者注:类型B的值 = 类型B(类型A的值)*** **译者注:类型 B 的值 = 类型 B(类型 A 的值)**
示例: 示例:
@@ -292,10 +299,12 @@ Go 程序的执行(程序启动)顺序如下:
c := int(a) c := int(a)
d := IZ(c) d := IZ(c)
##4.2.7 Go 命名规范 ## 4.2.7 Go 命名规范
干净、可读的代码和简洁性是 Go 追求的主要目标。通过 gofmt 来强制实现统一的代码风格。Go 语言中对象的命名也应该是简洁且有意义的。像 Java 和 Python 中那样使用混合着大小写和下划线的冗长的名称会严重降低代码的可读性。名称不需要指出自己所属的包,因为在调用的时候会使用包名作为限定符。返回某个对象的函数或方法的名称一般都是使用名词,没有 “Get...” 之类的字符( ***译者注:个人觉得这个有点牵强*** ),如果是用于修改某个对象,则使用 “SetName”。有必须要的话可以使用大小写混合的方式如 MixedCaps 或 mixedCaps而不是使用下划线来分割多个名称。
干净、可读的代码和简洁性是 Go 追求的主要目标。通过 gofmt 来强制实现统一的代码风格。Go 语言中对象的命名也应该是简洁且有意义的。像 Java 和 Python 中那样使用混合着大小写和下划线的冗长的名称会严重降低代码的可读性。名称不需要指出自己所属的包,因为在调用的时候会使用包名作为限定符。返回某个对象的函数或方法的名称一般都是使用名词,没有 “Get...” 之类的字符( **译者注:个人觉得这个有点牵强** ),如果是用于修改某个对象,则使用 “SetName”。有必须要的话可以使用大小写混合的方式如 MixedCaps 或 mixedCaps而不是使用下划线来分割多个名称。
## 链接
##链接
- [目录](directory.md) - [目录](directory.md)
- 上一节:[文件名、关键字与标识符](04.1.md) - 上一节:[文件名、关键字与标识符](04.1.md)
- 下一节:[常量](04.3.md) - 下一节:[常量](04.3.md)

View File

@@ -1,4 +1,5 @@
#4.3 常量 # 4.3 常量
常量使用关键字 const 定义,用于存储不会改变的数据。 常量使用关键字 const 定义,用于存储不会改变的数据。
存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。 存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
@@ -20,7 +21,7 @@
- 正确的做法:`const c1 = 2/3` - 正确的做法:`const c1 = 2/3`
- 错误的做法:`const c2 = getNumber()` // 引发构建错误: `getNumber() used as value` - 错误的做法:`const c2 = getNumber()` // 引发构建错误: `getNumber() used as value`
***译者注因为在编译期间自定义函数均属于未知因此无法用于常量的赋值但内置函数可以使用len()*** **译者注因为在编译期间自定义函数均属于未知因此无法用于常量的赋值但内置函数可以使用len()**
数字型的常量是没有大小和符号的,并且可以使用任何精度而不会导致溢出: 数字型的常量是没有大小和符号的,并且可以使用任何精度而不会导致溢出:
@@ -69,9 +70,9 @@
c c
) )
***译者注:关于 iota 的使用涉及到非常复杂多样的情况,这里作者解释的并不清晰,因为很难对 iota 的用法进行直观的文字描述。如希望进一步了解,请观看视频教程 [《Go编程基础》](https://github.com/Unknwon/go-fundamental-programming) [第四课:常量与运算符](https://github.com/Unknwon/go-fundamental-programming/blob/master/lecture4/lecture4.md)*** **译者注:关于 iota 的使用涉及到非常复杂多样的情况,这里作者解释的并不清晰,因为很难对 iota 的用法进行直观的文字描述。如希望进一步了解,请观看视频教程 [《Go编程基础》](https://github.com/Unknwon/go-fundamental-programming) [第四课:常量与运算符](https://github.com/Unknwon/go-fundamental-programming/blob/master/lectures/lecture4.md)**
`iota` 也可以用在表达式中,如:`iota + 50`。在每遇到一个新的常量块或单个常量声明时, `iota` 都会重置为 0 ***译者注:简单地讲,每遇到一次 const 关键字iota 就重置为 0*** )。 `iota` 也可以用在表达式中,如:`iota + 50`。在每遇到一个新的常量块或单个常量声明时, `iota` 都会重置为 0 **译者注:简单地讲,每遇到一次 const 关键字iota 就重置为 0** )。
当然,常量之所以为常量就是恒定不变的量,因此我们无法在程序运行过程中修改它的值;如果你在代码中试图修改常量的值则会引发编译错误。 当然,常量之所以为常量就是恒定不变的量,因此我们无法在程序运行过程中修改它的值;如果你在代码中试图修改常量的值则会引发编译错误。
@@ -102,7 +103,8 @@
**注意事项** 作为约定,常量的标识符主要使用大写字母,标识符中各个部分的连接字符可用小写字母以便区分,如:`const INCHTOwCM = 2.54`;这样不仅增强了可读性,而且不会与第 4.2 节中描述的可见性规则冲突。 **注意事项** 作为约定,常量的标识符主要使用大写字母,标识符中各个部分的连接字符可用小写字母以便区分,如:`const INCHTOwCM = 2.54`;这样不仅增强了可读性,而且不会与第 4.2 节中描述的可见性规则冲突。
##链接 ## 链接
- [目录](directory.md) - [目录](directory.md)
- 上一节:[Go 程序的基本结构和要素](04.2.md) - 上一节:[Go 程序的基本结构和要素](04.2.md)
- 下一节:[变量](04.4.md) - 下一节:[变量](04.4.md)

View File

@@ -1,5 +1,7 @@
#4.4 变量 # 4.4 变量
##4.4.1 简介
## 4.4.1 简介
声明变量的一般形式是使用 `var` 关键字:`var identifier type` 声明变量的一般形式是使用 `var` 关键字:`var identifier type`
需要注意的是Go 和许多编程语言不同它在声明变量时将变量的类型放在变量的名称之后。Go 为什么要选择这么做呢? 需要注意的是Go 和许多编程语言不同它在声明变量时将变量的类型放在变量的名称之后。Go 为什么要选择这么做呢?
@@ -107,7 +109,8 @@ Example 4.5 [goos.go](examples/chapter_4/goos.go)
这里用到了 `Printf` 的格式化输出的功能(第 4.4.3 节)。 这里用到了 `Printf` 的格式化输出的功能(第 4.4.3 节)。
##4.4.2 值类型和引用类型 ## 4.4.2 值类型和引用类型
程序中所用到的内存在计算机中使用一堆箱子来表示(这也是人们在讲解它的时候的画法),这些箱子被称为 “ 字 ”。根据不同的处理器以及操作系统类型,所有的字都具有 32 位4 字节)或 64 位8 字节)的相同长度;所有的字都使用相关的内存地址来进行表示(以十六进制数表示)。 程序中所用到的内存在计算机中使用一堆箱子来表示(这也是人们在讲解它的时候的画法),这些箱子被称为 “ 字 ”。根据不同的处理器以及操作系统类型,所有的字都具有 32 位4 字节)或 64 位8 字节)的相同长度;所有的字都使用相关的内存地址来进行表示(以十六进制数表示)。
所有像 intfloatboolstring 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值: 所有像 intfloatboolstring 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值:
@@ -153,7 +156,8 @@ Example 4.5 [goos.go](examples/chapter_4/goos.go)
函数 `fmt.Print``fmt.Println` 会自动使用格式化标识符 `%v` 对字符串进行格式化,两者都会在每个参数之间自动增加空格,而后者还会在字符串的最后加上一个换行符。例如:`fmt.Print("Hello:", 23)` 将输出:`Hello: 23` 函数 `fmt.Print``fmt.Println` 会自动使用格式化标识符 `%v` 对字符串进行格式化,两者都会在每个参数之间自动增加空格,而后者还会在字符串的最后加上一个换行符。例如:`fmt.Print("Hello:", 23)` 将输出:`Hello: 23`
##4.4.4 简短形式,使用 := 赋值操作符 ## 4.4.4 简短形式,使用 := 赋值操作符
我们知道可以在变量的初始化时省略变量的类型而由系统自动推断,而这个时候再在 Example 4.4.1 的最后一个声明语句写上 `var` 关键字就显得有些多余了,因此我们可以将它们简写为 `a := 50``b := false` 我们知道可以在变量的初始化时省略变量的类型而由系统自动推断,而这个时候再在 Example 4.4.1 的最后一个声明语句写上 `var` 关键字就显得有些多余了,因此我们可以将它们简写为 `a := 50``b := false`
a 和 b 的类型int 和 bool将由编译器自动推断。 a 和 b 的类型int 和 bool将由编译器自动推断。
@@ -203,7 +207,8 @@ a 和 b 的类型int 和 bool将由编译器自动推断。
并行赋值也被用于当一个函数返回多个返回值时,比如这里的 `val` 和错误 `err` 是通过调用 `Func1` 函数同时得到:`val, err = Func1(var1)` 并行赋值也被用于当一个函数返回多个返回值时,比如这里的 `val` 和错误 `err` 是通过调用 `Func1` 函数同时得到:`val, err = Func1(var1)`
##4.4.5 init 函数 ## 4.4.5 init 函数
变量除了可以在全局声明中初始化,也可以在 init() 函数中初始化。这是一类非常特殊的函数,它不能够被人为调用,而是在每个包完成初始化后自动执行,并且执行优先级比 main() 函数高。 变量除了可以在全局声明中初始化,也可以在 init() 函数中初始化。这是一类非常特殊的函数,它不能够被人为调用,而是在每个包完成初始化后自动执行,并且执行优先级比 main() 函数高。
每一个源文件都可以包含且只包含一个 init() 函数。初始化总是以单线程执行,并且按照包的依赖关系顺序执行。 每一个源文件都可以包含且只包含一个 init() 函数。初始化总是以单线程执行,并且按照包的依赖关系顺序执行。
@@ -292,7 +297,8 @@ init() 函数也经常被用在当一个程序开始之前调用后台执行的
print(a) print(a)
} }
##链接 ## 链接
- [目录](directory.md) - [目录](directory.md)
- 上一节:[常量](04.3.md) - 上一节:[常量](04.3.md)
- 下一节:[基本类型和运算符](04.5.md) - 下一节:[基本类型和运算符](04.5.md)

View File

@@ -1,4 +1,5 @@
#4.5 基本类型和运算符 # 4.5 基本类型和运算符
我们将在这个部分讲解有关布尔型、数字型和字符型的相关知识。 我们将在这个部分讲解有关布尔型、数字型和字符型的相关知识。
表达式是一种特定的类型的值,它可以由其它的值以及运算符组合而成。每个类型都定义了可以和自己结合的运算符集合,如果你使用了不在这个集合中的运算符,则会在编译时获得编译错误。 表达式是一种特定的类型的值,它可以由其它的值以及运算符组合而成。每个类型都定义了可以和自己结合的运算符集合,如果你使用了不在这个集合中的运算符,则会在编译时获得编译错误。
@@ -9,7 +10,8 @@
你可以在第 4.5.3 节找到有关运算符优先级的相关信息,优先级越高的运算符在条件相同的情况下将被优先执行。但是你可以通过使用括号将其中的表达式括起来,以人为地提升某个表达式的运算优先级。 你可以在第 4.5.3 节找到有关运算符优先级的相关信息,优先级越高的运算符在条件相同的情况下将被优先执行。但是你可以通过使用括号将其中的表达式括起来,以人为地提升某个表达式的运算优先级。
##4.5.1 布尔类型 bool ## 4.5.1 布尔类型 bool
一个简单的例子:`var b bool = true` 一个简单的例子:`var b bool = true`
布尔型的值只可以是常量 true 或者 false。 布尔型的值只可以是常量 true 或者 false。
@@ -75,8 +77,10 @@ Go 语言中包含以下逻辑运算符:
对于布尔值的好的命名能够很好地提升代码的可读性,例如以 `is` 或者 `Is` 开头的 `isSorted``isFinished``isVisivle`,使用这样的命名能够在阅读代码的获得阅读正常语句一样的良好体验,例如标准库中的 `unicode.IsDigit(ch)`(第 4.5.5 节)。 对于布尔值的好的命名能够很好地提升代码的可读性,例如以 `is` 或者 `Is` 开头的 `isSorted``isFinished``isVisivle`,使用这样的命名能够在阅读代码的获得阅读正常语句一样的良好体验,例如标准库中的 `unicode.IsDigit(ch)`(第 4.5.5 节)。
##4.5.2 数字类型 ## 4.5.2 数字类型
###4.5.2.1 整型 int 和浮点型 float
### 4.5.2.1 整型 int 和浮点型 float
Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码(二的补码,详情参见:[http://en.wikipedia.org/wiki/Two's_complement](http://en.wikipedia.org/wiki/Two's_complement))。 Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码(二的补码,详情参见:[http://en.wikipedia.org/wiki/Two's_complement](http://en.wikipedia.org/wiki/Two's_complement))。
Go 也有基于架构的类型例如int、uint 和 uintptr。 Go 也有基于架构的类型例如int、uint 和 uintptr。
@@ -196,7 +200,8 @@ Example 4.9 [casting.go](examples/chapter_4/casting.go)
**问题 4.1** int 和 int64 是相同的类型吗? **问题 4.1** int 和 int64 是相同的类型吗?
###4.5.2.2 复数 ### 4.5.2.2 复数
Go 拥有以下复数类型: Go 拥有以下复数类型:
complex64 (32 位实数和虚数) complex64 (32 位实数和虚数)
@@ -220,7 +225,8 @@ Go 拥有以下复数类型:
复数支持和其它数字类型一样的运算。当你使用等号 `==` 或者不等号 `!=` 对复数进行比较运算时,注意对精确度的把握。`cmath` 包中包含了一些操作复数的公共方法。如果你对内存的要求不是特别高,最好使用 complex128 作为计算类型,因为相关函数都使用这个类型的参数。 复数支持和其它数字类型一样的运算。当你使用等号 `==` 或者不等号 `!=` 对复数进行比较运算时,注意对精确度的把握。`cmath` 包中包含了一些操作复数的公共方法。如果你对内存的要求不是特别高,最好使用 complex128 作为计算类型,因为相关函数都使用这个类型的参数。
###4.5.2.3 位运算 ### 4.5.2.3 位运算
位运算只能用于整数类型的变量,且需当它们拥有等长位模式时。 位运算只能用于整数类型的变量,且需当它们拥有等长位模式时。
`%b` 是用于表示位的格式化标识符。 `%b` 是用于表示位的格式化标识符。
@@ -308,14 +314,16 @@ Go 拥有以下复数类型:
flag := Active | Send // == 3 flag := Active | Send // == 3
###4.5.2.4 逻辑运算符 ### 4.5.2.4 逻辑运算符
Go 中拥有以下逻辑运算符`==``!=` 4.5.1 )、`<``<=``>``>=` Go 中拥有以下逻辑运算符`==``!=` 4.5.1 )、`<``<=``>``>=`
它们之所以被称为逻辑运算符是因为它们的运算结果总是为布尔值 `bool`例如 它们之所以被称为逻辑运算符是因为它们的运算结果总是为布尔值 `bool`例如
b3:= 10 > 5 // b3 is true b3:= 10 > 5 // b3 is true
###4.5.2.5 算术运算符 ### 4.5.2.5 算术运算符
常见可用于整数和浮点数的二元运算符有 `+``-``*``/` 常见可用于整数和浮点数的二元运算符有 `+``-``*``/`
相对于一般规则而言Go 在进行字符串拼接时允许使用对运算符 `+` 的重载,但 Go 本身不允许开发者进行自定义的运算符重载) 相对于一般规则而言Go 在进行字符串拼接时允许使用对运算符 `+` 的重载,但 Go 本身不允许开发者进行自定义的运算符重载)
@@ -341,7 +349,8 @@ Go 中拥有以下逻辑运算符:`==`、`!=`(第 4.5.1 节)、`<`、`<=`
在运算时 **溢出** 不会产生错误Go 会简单地将超出位数抛弃。如果你需要范围无限大的整数或者有理数(意味着只被限制于计算机内存),你可以使用标准库中的 `big` 包,该包提供了类似 `big.Int``big.Rat` 这样的类型(第 9.4 节)。 在运算时 **溢出** 不会产生错误Go 会简单地将超出位数抛弃。如果你需要范围无限大的整数或者有理数(意味着只被限制于计算机内存),你可以使用标准库中的 `big` 包,该包提供了类似 `big.Int``big.Rat` 这样的类型(第 9.4 节)。
###4.5.2.6 随机数 ### 4.5.2.6 随机数
一些像游戏或者统计学类的应用需要用到随机数。`rand` 包实现了伪随机数的生成。 一些像游戏或者统计学类的应用需要用到随机数。`rand` 包实现了伪随机数的生成。
Example 4.10 [random.go](examples/chapter_4/random.go) 演示了如何生成 10 个非负随机数: Example 4.10 [random.go](examples/chapter_4/random.go) 演示了如何生成 10 个非负随机数:
@@ -380,7 +389,8 @@ Example 4.10 [random.go](examples/chapter_4/random.go) 演示了如何生成 10
你可以使用 `Seed(value)` 函数来提供伪随机数的生成种子,一般情况下都会使用当前时间的纳秒级数字(第 4.8 节)。 你可以使用 `Seed(value)` 函数来提供伪随机数的生成种子,一般情况下都会使用当前时间的纳秒级数字(第 4.8 节)。
##4.5.3 运算符与优先级 ## 4.5.3 运算符与优先级
有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低: 有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:
优先级 运算符 优先级 运算符
@@ -394,7 +404,8 @@ Example 4.10 [random.go](examples/chapter_4/random.go) 演示了如何生成 10
当然,你可以通过使用括号来临时提升某个表达式的整体运算优先级。 当然,你可以通过使用括号来临时提升某个表达式的整体运算优先级。
##4.5.4 类型别名 ## 4.5.4 类型别名
当你在使用某个类型时,你可以给它起另一个名字,然后你就可以在你的代码中使用新的名字(用于简化名称或解决名称冲突)。 当你在使用某个类型时,你可以给它起另一个名字,然后你就可以在你的代码中使用新的名字(用于简化名称或解决名称冲突)。
在 `type TZ int` 中TZ 就是 int 类型的新名称(用于表示程序中的时区),然后就可以使用 TZ 来操作 int 类型的数据。 在 `type TZ int` 中TZ 就是 int 类型的新名称(用于表示程序中的时区),然后就可以使用 TZ 来操作 int 类型的数据。
@@ -416,7 +427,8 @@ Example 4.11 [type.go](examples/chapter_4/type.go)
**练习 4.5** 定义一个 `string` 的类型别名 `Rope`并声明一个该类型的变量 **练习 4.5** 定义一个 `string` 的类型别名 `Rope`并声明一个该类型的变量
##4.5.5 字符类型 ## 4.5.5 字符类型
严格来说这并不是 Go 语言的一个类型字符只是整数的特殊用例`byte` 类型是 `uint8` 的别名对于只占用 1 个字节的传统 ASCII 编码的字符来说完全没有问题例如`var ch byte = 'A'`字符使用单引号括起来 严格来说这并不是 Go 语言的一个类型字符只是整数的特殊用例`byte` 类型是 `uint8` 的别名对于只占用 1 个字节的传统 ASCII 编码的字符来说完全没有问题例如`var ch byte = 'A'`字符使用单引号括起来
ASCII 码表中A 的值是 65而使用 16 进制表示则为 41所以下面的写法是等效的 ASCII 码表中A 的值是 65而使用 16 进制表示则为 41所以下面的写法是等效的
@@ -460,9 +472,10 @@ Example 4.12 [char.go](examples/chapter_4/char.go)
这些函数返回一个布尔值 `utf8` 拥有更多与 rune 相关的函数 这些函数返回一个布尔值 `utf8` 拥有更多与 rune 相关的函数
***译者注关于类型的相关讲解可参考视频教程 Go编程基础 3 [类型与变量](https://github.com/Unknwon/go-fundamental-programming/blob/master/lecture3/lecture3.md)*** **译者注:关于类型的相关讲解可参考视频教程 《Go编程基础》 第 3 课:[类型与变量](https://github.com/Unknwon/go-fundamental-programming/blob/master/lectures/lecture3.md)**
## 链接
##链接
- [目录](directory.md) - [目录](directory.md)
- 上一节[变量](04.4.md) - 上一节[变量](04.4.md)
- 下一节[字符串](04.6.md) - 下一节[字符串](04.6.md)

View File

@@ -1,4 +1,5 @@
#4.6 字符串 # 4.6 字符串
字符串是 UTF-8 字符的一个序列(当字符为 ASCII 码时则占用 1 个字节,其它字符根据需要占用 2-4 个字节。UTF-8 是被广泛使用的编码格式,是文本文件的标准编码,其它包括 XML 和 JSON 在内也都使用该编码。由于该编码对占用字节长度的不定性Go 中的字符串也可能根据需要占用 1 至 4 个字节(示例见第 4.6 节),这与其它语言如 C++、Java 或者 Python 不同Java 始终使用 2 个字节。Go 这样做的好处是不仅减少了内存和硬盘空间占用,同时也不用像其它语言那样需要对使用 UTF-8 字符集的文本进行编码和解码。 字符串是 UTF-8 字符的一个序列(当字符为 ASCII 码时则占用 1 个字节,其它字符根据需要占用 2-4 个字节。UTF-8 是被广泛使用的编码格式,是文本文件的标准编码,其它包括 XML 和 JSON 在内也都使用该编码。由于该编码对占用字节长度的不定性Go 中的字符串也可能根据需要占用 1 至 4 个字节(示例见第 4.6 节),这与其它语言如 C++、Java 或者 Python 不同Java 始终使用 2 个字节。Go 这样做的好处是不仅减少了内存和硬盘空间占用,同时也不用像其它语言那样需要对使用 UTF-8 字符集的文本进行编码和解码。
字符串是一种值类型,且值不可变,即创建某个文本后你无法再次修改这个文本的内容;更深入地讲,字符串是字节的定长数组。 字符串是一种值类型,且值不可变,即创建某个文本后你无法再次修改这个文本的内容;更深入地讲,字符串是字节的定长数组。
@@ -64,7 +65,8 @@ Go 支持以下 2 种形式的字面值:
创建一个用于统计字节和字符rune的程序并对字符串 `asSASA ddd dsjkdsjs dk` 进行分析,然后再分析 `asSASA ddd dsjkdsjsこん dk`,最后解释两者不同的原因(提示:使用 `unicode/utf8` 包)。 创建一个用于统计字节和字符rune的程序并对字符串 `asSASA ddd dsjkdsjs dk` 进行分析,然后再分析 `asSASA ddd dsjkdsjsこん dk`,最后解释两者不同的原因(提示:使用 `unicode/utf8` 包)。
##链接 ## 链接
- [目录](directory.md) - [目录](directory.md)
- 上一节:[基本类型和运算符](04.5.md) - 上一节:[基本类型和运算符](04.5.md)
- 下一节:[strings 和 strconv 包](04.7.md) - 下一节:[strings 和 strconv 包](04.7.md)

View File

@@ -1,7 +1,9 @@
#4.7 strings 和 strconv 包 # 4.7 strings 和 strconv 包
作为一种基本数据结构每种语言都有一些对于字符串的预定义处理函数。Go 中使用 `strings` 包来完成对字符串的主要操作。 作为一种基本数据结构每种语言都有一些对于字符串的预定义处理函数。Go 中使用 `strings` 包来完成对字符串的主要操作。
##4.7.1 前缀和后缀 ## 4.7.1 前缀和后缀
`HasPrefix` 判断字符串 `s` 是否以 `prefix` 开头: `HasPrefix` 判断字符串 `s` 是否以 `prefix` 开头:
strings.HasPrefix(s, prefix string) bool strings.HasPrefix(s, prefix string) bool
@@ -31,12 +33,14 @@ Example 4.13 [presuffix.go](examples/chapter_4/presuffix.go)
这个例子同样演示了转义字符 `\` 和格式化字符串的使用。 这个例子同样演示了转义字符 `\` 和格式化字符串的使用。
##4.7.2 字符串包含关系 ## 4.7.2 字符串包含关系
`Contains` 判断字符串 `s` 是否包含 `substr` `Contains` 判断字符串 `s` 是否包含 `substr`
strings.Contains(s, substr string) bool strings.Contains(s, substr string) bool
##4.7.3 判断子字符串或字符在父字符串中出现的位置(索引) ## 4.7.3 判断子字符串或字符在父字符串中出现的位置(索引)
`Index` 返回字符串 `str` 在字符串 `s` 中的索引(`str` 的第一个字符的索引),-1 表示字符串 `s` 不包含字符串 `str` `Index` 返回字符串 `str` 在字符串 `s` 中的索引(`str` 的第一个字符的索引),-1 表示字符串 `s` 不包含字符串 `str`
strings.Index(s, str string) int strings.Index(s, str string) int
@@ -80,12 +84,14 @@ Example 4.14 [index_in_string.go](examples/chapter_4/index_in_string.go)
The position of the last instance of "Hi" is: 14 The position of the last instance of "Hi" is: 14
The position of "Burger" is: -1 The position of "Burger" is: -1
##4.7.4 字符串替换 ## 4.7.4 字符串替换
`Replace` 用于将字符串 `str` 中的前 `n` 个字符串 `old` 替换为字符串 `new`,并返回一个新的字符串,如果 `n = -1` 则替换所有字符串 `old` 为字符串 `new` `Replace` 用于将字符串 `str` 中的前 `n` 个字符串 `old` 替换为字符串 `new`,并返回一个新的字符串,如果 `n = -1` 则替换所有字符串 `old` 为字符串 `new`
strings.Replace(str, old, new, n) string strings.Replace(str, old, new, n) string
##4.7.5 统计字符串出现次数 ## 4.7.5 统计字符串出现次数
`Count` 用于计算字符串 `str` 在字符串 `s` 中出现的非重叠次数: `Count` 用于计算字符串 `str` 在字符串 `s` 中出现的非重叠次数:
strings.Count(s, str string) int strings.Count(s, str string) int
@@ -115,7 +121,8 @@ Example 4.15 [count_substring.go](examples/chapter_4/count_substring.go)
Number of H's in Hello, how is it going, Hugo? is: 2 Number of H's in Hello, how is it going, Hugo? is: 2
Number of double gs in gggggggggg is: 5 Number of double gs in gggggggggg is: 5
##4.7.6 重复字符串 ## 4.7.6 重复字符串
`Repeat` 用于重复 `count` 次字符串 `s` 并返回一个新的字符串: `Repeat` 用于重复 `count` 次字符串 `s` 并返回一个新的字符串:
strings.Repeat(s, count int) string strings.Repeat(s, count int) string
@@ -141,7 +148,8 @@ Example 4.16 [repeat_string.go](examples/chapter_4/repeat_string.go)
The new repeated string is: Hi there! Hi there! Hi there! The new repeated string is: Hi there! Hi there! Hi there!
##4.7.7 修改字符串大小写 ## 4.7.7 修改字符串大小写
`ToLower` 将字符串中的 Unicode 字符全部转换为相应的小写字符: `ToLower` 将字符串中的 Unicode 字符全部转换为相应的小写字符:
strings.ToLower(s) string strings.ToLower(s) string
@@ -177,17 +185,20 @@ Example 4.17 [toupper_lower.go](examples/chapter_4/toupper_lower.go)
The lowercase string is: hey, how are you george? The lowercase string is: hey, how are you george?
The uppercase string is: HEY, HOW ARE YOU GEORGE? The uppercase string is: HEY, HOW ARE YOU GEORGE?
##4.7.8 修剪字符串 ## 4.7.8 修剪字符串
你可以使用 `strings.TrimSpace(s)` 来剔除字符串开头和结尾的空白符号;如果你想要剔除指定字符,则可以使用 `strings.Trim(s, "cut")` 来将开头和结尾的 `cut` 去除掉。该函数的第二个参数可以包含任何字符,如果你只想剔除开头或者结尾的字符串,则可以使用 `TrimLeft` 或者 `TrimRight` 来实现。 你可以使用 `strings.TrimSpace(s)` 来剔除字符串开头和结尾的空白符号;如果你想要剔除指定字符,则可以使用 `strings.Trim(s, "cut")` 来将开头和结尾的 `cut` 去除掉。该函数的第二个参数可以包含任何字符,如果你只想剔除开头或者结尾的字符串,则可以使用 `TrimLeft` 或者 `TrimRight` 来实现。
##4.7.9 分割字符串 ## 4.7.9 分割字符串
`strings.Fields(s)` 将会利用 1 个或多个空白符号来作为动态长度的分隔符将字符串分割成若干小块,并返回一个 slice如果字符串只包含空白符号则返回一个长度为 0 的 slice。 `strings.Fields(s)` 将会利用 1 个或多个空白符号来作为动态长度的分隔符将字符串分割成若干小块,并返回一个 slice如果字符串只包含空白符号则返回一个长度为 0 的 slice。
`strings.Split(s, sep)` 用于自定义分割符号来对指定字符串进行分割,同样返回 slice。 `strings.Split(s, sep)` 用于自定义分割符号来对指定字符串进行分割,同样返回 slice。
因为这 2 个函数都会返回 slice所以习惯使用 for-range 循环来对其进行处理(第 7.3 节)。 因为这 2 个函数都会返回 slice所以习惯使用 for-range 循环来对其进行处理(第 7.3 节)。
##4.7.10 拼接 slice 到字符串 ## 4.7.10 拼接 slice 到字符串
`Join` 用于将元素类型为 string 的 slice 使用分割符号来拼接组成一个字符串: `Join` 用于将元素类型为 string 的 slice 使用分割符号来拼接组成一个字符串:
Strings.Join(sl []string, sep string) Strings.Join(sl []string, sep string)
@@ -230,13 +241,15 @@ Example 4.18 [strings_splitjoin.go](examples/chapter_4/strings_splitjoin.go)
其它有关字符串操作的文档请参阅官方文档 [http://golang.org/pkg/strings/](http://golang.org/pkg/strings/) ***译者注:国内用户可访问 [http://docs.studygolang.com/pkg/strings/](http://docs.studygolang.com/pkg/strings/)*** )。 其它有关字符串操作的文档请参阅官方文档 [http://golang.org/pkg/strings/](http://golang.org/pkg/strings/) ***译者注:国内用户可访问 [http://docs.studygolang.com/pkg/strings/](http://docs.studygolang.com/pkg/strings/)*** )。
##4.7.11 从字符串中读取内容 ## 4.7.11 从字符串中读取内容
函数 `strings.NewReader(str)` 用于生成一个 `Reader` 并读取字符串中的内容,然后返回指向该 `Reader` 的指针,从其它类型读取内容的函数还有: 函数 `strings.NewReader(str)` 用于生成一个 `Reader` 并读取字符串中的内容,然后返回指向该 `Reader` 的指针,从其它类型读取内容的函数还有:
- `Read()` 从 []byte 中读取内容。 - `Read()` 从 []byte 中读取内容。
- `ReadByte()``ReadRune()` 从字符串中读取下一个 byte 或者 rune。 - `ReadByte()``ReadRune()` 从字符串中读取下一个 byte 或者 rune。
##4.7.12 字符串与其它类型的转换 ## 4.7.12 字符串与其它类型的转换
与字符串相关的类型转换都是通过 `strconv` 包实现的。 与字符串相关的类型转换都是通过 `strconv` 包实现的。
该包包含了一些变量用于获取程序运行的操作系统平台下 int 类型所占的位数,如:`strconv.IntSize` 该包包含了一些变量用于获取程序运行的操作系统平台下 int 类型所占的位数,如:`strconv.IntSize`
@@ -294,7 +307,8 @@ Example 4.19 [string_conversion.go](examples/chapter_4/string_conversion.go)
更多有关该包的讨论,请参阅官方文档 [http://golang.org/pkg/strconv/](http://golang.org/pkg/strconv/) ***译者注:国内用户可访问 [http://docs.studygolang.com/pkg/strconv/](http://docs.studygolang.com/pkg/strconv/)*** )。 更多有关该包的讨论,请参阅官方文档 [http://golang.org/pkg/strconv/](http://golang.org/pkg/strconv/) ***译者注:国内用户可访问 [http://docs.studygolang.com/pkg/strconv/](http://docs.studygolang.com/pkg/strconv/)*** )。
##链接 ## 链接
- [目录](directory.md) - [目录](directory.md)
- 上一节:[字符串](04.6.md) - 上一节:[字符串](04.6.md)
- 下一节:[时间和日期](04.8.md) - 下一节:[时间和日期](04.8.md)

View File

@@ -1,4 +1,5 @@
#4.8 时间和日期 # 4.8 时间和日期
`time` 包为我们提供了一个数据类型 `time.Time`(作为值使用)以及显示和测量时间和日期的功能函数。 `time` 包为我们提供了一个数据类型 `time.Time`(作为值使用)以及显示和测量时间和日期的功能函数。
当前时间可以使用 `time.Now()` 获取,或者使用 `t.Day()``t.Minute()` 等等来获取时间的一部分;你甚至可以自定义时间格式化字符串,例如: `fmt.Printf("%02d.%02d.%4d\n”, t.Day(), t.Month(), t.Year())` 将会输出 `21.07.2011` 当前时间可以使用 `time.Now()` 获取,或者使用 `t.Day()``t.Minute()` 等等来获取时间的一部分;你甚至可以自定义时间格式化字符串,例如: `fmt.Printf("%02d.%02d.%4d\n”, t.Day(), t.Month(), t.Year())` 将会输出 `21.07.2011`
@@ -15,7 +16,7 @@ Duration 类型表示两个连续时刻所相差的纳秒数,类型为 int64
21 Jul 2011 10:31 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://golang.org/pkg/time/) **译者注:国内用户可访问 [http://docs.studygolang.com/pkg/time/](http://docs.studygolang.com/pkg/time/)** )。
Example 4.20 [time.go](examples/chapter_4/time.go) Example 4.20 [time.go](examples/chapter_4/time.go)
@@ -51,7 +52,8 @@ Example 4.20 [time.go](examples/chapter_4/time.go)
如果你需要在应用程序在经过一定时间或周期执行某项任务(事件处理的特例),则可以使用 `time.After` 或者 `time.Ticker`:我们将会在第 14.5 节讨论这些有趣的事情。 另外,`time.SleepDuration d` 可以实现对某个进程(实质上是 goroutine时长为 d 的暂停。 如果你需要在应用程序在经过一定时间或周期执行某项任务(事件处理的特例),则可以使用 `time.After` 或者 `time.Ticker`:我们将会在第 14.5 节讨论这些有趣的事情。 另外,`time.SleepDuration d` 可以实现对某个进程(实质上是 goroutine时长为 d 的暂停。
##链接 ## 链接
- [目录](directory.md) - [目录](directory.md)
- 上一节:[strings 和 strconv 包](04.7.md) - 上一节:[strings 和 strconv 包](04.7.md)
- 下一节:[指针](04.9.md) - 下一节:[指针](04.9.md)

View File

@@ -1,4 +1,5 @@
#4.9 指针 # 4.9 指针
不像 Java 和 .NETGo 语言为程序员提供了控制数据结构的指针的能力但是你不能进行指针运算。通过给予程序员基本内存布局Go 语言允许你控制特定集合的数据结构、分配的数量以及内存访问模式,这些对构建运行良好的系统是非常重要的:指针对于性能的影响是不言而喻的,而如果你想要做的是系统编程、操作系统或者网络应用,指针更是不可或缺的一部分。 不像 Java 和 .NETGo 语言为程序员提供了控制数据结构的指针的能力但是你不能进行指针运算。通过给予程序员基本内存布局Go 语言允许你控制特定集合的数据结构、分配的数量以及内存访问模式,这些对构建运行良好的系统是非常重要的:指针对于性能的影响是不言而喻的,而如果你想要做的是系统编程、操作系统或者网络应用,指针更是不可或缺的一部分。
由于各种原因,指针对于使用面向对象编程的现代程序员来说可能显得有些陌生,不过我们将会在这一小节对此进行解释,并在未来的章节中展开深入讨论。 由于各种原因,指针对于使用面向对象编程的现代程序员来说可能显得有些陌生,不过我们将会在这一小节对此进行解释,并在未来的章节中展开深入讨论。
@@ -122,7 +123,8 @@ Example 4.23 [testcrash.go](examples/chapter_4/testcrash.go):
**问题 4.2** 列举 Go 语言中 * 号的所有用法。 **问题 4.2** 列举 Go 语言中 * 号的所有用法。
##链接 ## 链接
- [目录](directory.md) - [目录](directory.md)
- 上一节:[时间和日期](04.8.md) - 上一节:[时间和日期](04.8.md)
- 下一节:[控制结构](05.0.md) - 下一节:[控制结构](05.0.md)