mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-08-19 17:32:02 +08:00
Merge remote-tracking branch 'bob/master'
This commit is contained in:
15
README_gc.md
15
README_gc.md
@@ -9,13 +9,14 @@
|
|||||||
本书的主要译者是 [@无闻Unknwon](http://www.weibo.com/Obahua),是一名 Go 语言爱好者和传播者,目前是 [Go Walker](https://gowalker.org)、Gopm、[Gogs](http://gogs.io) 和 [Macaron](https://github.com/Unknwon/macaron) 创始人,极客学院签约讲师。
|
本书的主要译者是 [@无闻Unknwon](http://www.weibo.com/Obahua),是一名 Go 语言爱好者和传播者,目前是 [Go Walker](https://gowalker.org)、Gopm、[Gogs](http://gogs.io) 和 [Macaron](https://github.com/Unknwon/macaron) 创始人,极客学院签约讲师。
|
||||||
|
|
||||||
目前已由多位 Go 语言爱好者共同提交翻译内容,主要包括:
|
目前已由多位 Go 语言爱好者共同提交翻译内容,主要包括:
|
||||||
- [@zhanming](https://github.com/zhanming)
|
|
||||||
- themorecolor
|
- [@zhanming](https://github.com/zhanming)
|
||||||
- [@everyx](https://github.com/everyx)
|
- themorecolor
|
||||||
- [@chidouhu](https://github.com/chidouhu)
|
- [@everyx](https://github.com/everyx)
|
||||||
- [@spawnris](https://github.com/spawnris)
|
- [@chidouhu](https://github.com/chidouhu)
|
||||||
- [@domainname](https://github.com/domainname)
|
- [@spawnris](https://github.com/spawnris)
|
||||||
- [@leisore](https://github.com/leisore)
|
- [@domainname](https://github.com/domainname)
|
||||||
|
- [@leisore](https://github.com/leisore)
|
||||||
|
|
||||||
## 适用人群
|
## 适用人群
|
||||||
|
|
||||||
|
@@ -474,7 +474,7 @@ var ch byte = 65 或 var ch byte = '\x41'
|
|||||||
|
|
||||||
(`\x` 总是紧跟着长度为 2 的 16 进制数)
|
(`\x` 总是紧跟着长度为 2 的 16 进制数)
|
||||||
|
|
||||||
另外一种可能的写法是 `\` 后面紧跟着长度为 3 的十进制数,例如:`\377`。
|
另外一种可能的写法是 `\` 后面紧跟着长度为 3 的八进制数,例如:`\377`。
|
||||||
|
|
||||||
不过 Go 同样支持 Unicode(UTF-8),因此字符同样称为 Unicode 代码点或者 runes,并在内存中使用 int 来表示。在文档中,一般使用格式 U+hhhh 来表示,其中 h 表示一个 16 进制数。其实 `rune` 也是 Go 当中的一个类型,并且是 `int32` 的别名。
|
不过 Go 同样支持 Unicode(UTF-8),因此字符同样称为 Unicode 代码点或者 runes,并在内存中使用 int 来表示。在文档中,一般使用格式 U+hhhh 来表示,其中 h 表示一个 16 进制数。其实 `rune` 也是 Go 当中的一个类型,并且是 `int32` 的别名。
|
||||||
|
|
||||||
|
@@ -27,14 +27,14 @@ package main
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
x := Min(1, 3, 2, 0)
|
x := min(1, 3, 2, 0)
|
||||||
fmt.Printf("The minimum is: %d\n", x)
|
fmt.Printf("The minimum is: %d\n", x)
|
||||||
arr := []int{7,9,3,5,1}
|
arr := []int{7,9,3,5,1}
|
||||||
x = Min(arr...)
|
x = min(arr...)
|
||||||
fmt.Printf("The minimum in the array arr is: %d", x)
|
fmt.Printf("The minimum in the array arr is: %d", x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Min(a ...int) int {
|
func min(a ...int) int {
|
||||||
if len(a)==0 {
|
if len(a)==0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@@ -11,17 +11,17 @@ package main
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
Function1()
|
function1()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Function1() {
|
func function1() {
|
||||||
fmt.Printf("In Function1 at the top\n")
|
fmt.Printf("In function1 at the top\n")
|
||||||
defer Function2()
|
defer function2()
|
||||||
fmt.Printf("In Function1 at the bottom!\n")
|
fmt.Printf("In function1 at the bottom!\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Function2() {
|
func function2() {
|
||||||
fmt.Printf("Function2: Deferred until the end of the calling function!")
|
fmt.Printf("function2: Deferred until the end of the calling function!")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -121,7 +121,7 @@ func sum(a []int) int {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func main {
|
func main() {
|
||||||
var arr = [5]int{0, 1, 2, 3, 4}
|
var arr = [5]int{0, 1, 2, 3, 4}
|
||||||
sum(arr[:])
|
sum(arr[:])
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ v := make([]int, 10, 50)
|
|||||||
这样分配一个有 50 个 int 值的数组,并且创建了一个长度为 10,容量为 50 的 切片 v,该 切片 指向数组的前 10 个元素。
|
这样分配一个有 50 个 int 值的数组,并且创建了一个长度为 10,容量为 50 的 切片 v,该 切片 指向数组的前 10 个元素。
|
||||||
|
|
||||||
**问题 7.3** 给定 `s := make([]byte, 5)`,len(s) 和 cap(s) 分别是多少?`s = s[2:4]`,len(s) 和 cap(s) 又分别是多少?
|
**问题 7.3** 给定 `s := make([]byte, 5)`,len(s) 和 cap(s) 分别是多少?`s = s[2:4]`,len(s) 和 cap(s) 又分别是多少?
|
||||||
**问题 7.4** 假设 `s1 := []byte{'p', 'o', 'e', 'm'}` 且 `s2 := d[2:]`,s2 的值是多少?如果我们执行 `s2[1] == 't'`,s1 和 s2 现在的值又分配是多少?
|
**问题 7.4** 假设 `s1 := []byte{'p', 'o', 'e', 'm'}` 且 `s2 := s1[2:]`,s2 的值是多少?如果我们执行 `s2[1] = 't'`,s1 和 s2 现在的值又分别是多少?
|
||||||
|
|
||||||
## 7.2.5 多维 切片
|
## 7.2.5 多维 切片
|
||||||
|
|
||||||
|
@@ -44,7 +44,7 @@ func AppendByte(slice []byte, data ...byte) []byte {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`func copy(dst, src []T) int` copy 方法将类型为 T 的切片从源地址 src 拷贝到目标地址 dst,覆盖 dst 的相关元素,并且返回拷贝的元素个数。源地址和目标地址可能会有重叠。拷贝个数是 src 和 dst 的长度最小值。如果 src 是字符串那么元素类型就是 byte。如果你还想继续使用 src,在拷贝技术后执行 `src = dst`。
|
`func copy(dst, src []T) int` copy 方法将类型为 T 的切片从源地址 src 拷贝到目标地址 dst,覆盖 dst 的相关元素,并且返回拷贝的元素个数。源地址和目标地址可能会有重叠。拷贝个数是 src 和 dst 的长度最小值。如果 src 是字符串那么元素类型就是 byte。如果你还想继续使用 src,在拷贝结束后执行 `src = dst`。
|
||||||
|
|
||||||
**练习 7.9**
|
**练习 7.9**
|
||||||
|
|
||||||
|
@@ -27,7 +27,7 @@ map 也可以用函数作为自己的值,这样就可以用来做分支结构
|
|||||||
|
|
||||||
key1 对应的值可以通过赋值符号来设置为 `val1:map1[key1] = val1`。
|
key1 对应的值可以通过赋值符号来设置为 `val1:map1[key1] = val1`。
|
||||||
|
|
||||||
令 `v: = map1[key1]` 可以将 key1 对应的值赋值为 v;如果 map 中没有 key1 存在,那么 v 将被赋值为 map1 的值类型的空值。
|
令 `v := map1[key1]` 可以将 key1 对应的值赋值为 v;如果 map 中没有 key1 存在,那么 v 将被赋值为 map1 的值类型的空值。
|
||||||
|
|
||||||
常用的 `len(map1)` 方法可以获得 map 中的 pair 数目,这个数目是可以伸缩的,因为 map-pairs 在运行时可以动态添加和删除。
|
常用的 `len(map1)` 方法可以获得 map 中的 pair 数目,这个数目是可以伸缩的,因为 map-pairs 在运行时可以动态添加和删除。
|
||||||
|
|
||||||
|
@@ -53,7 +53,7 @@ func main() {
|
|||||||
但是如果你想要一个排序的列表你最好使用结构体切片,这样会更有效:
|
但是如果你想要一个排序的列表你最好使用结构体切片,这样会更有效:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type struct {
|
type name struct {
|
||||||
key string
|
key string
|
||||||
value int
|
value int
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,6 @@ func main() {
|
|||||||
for k, v := range invMap {
|
for k, v := range invMap {
|
||||||
fmt.Printf("Key: %v, Value: %v / ", k, v)
|
fmt.Printf("Key: %v, Value: %v / ", k, v)
|
||||||
}
|
}
|
||||||
fmt.Println()
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
0
eBook/09.5.md
Executable file → Normal file
0
eBook/09.5.md
Executable file → Normal file
0
eBook/09.8.md
Executable file → Normal file
0
eBook/09.8.md
Executable file → Normal file
@@ -7,7 +7,11 @@ Go 开发者不需要写代码来释放程序中不再使用的变量和结构
|
|||||||
如果想知道当前的内存状态,可以使用:
|
如果想知道当前的内存状态,可以使用:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
fmt.Printf("%d\n", runtime.MemStats.Alloc/1024)
|
// fmt.Printf("%d\n", runtime.MemStats.Alloc/1024)
|
||||||
|
// 此处代码在 Go 1.5.1下不再有效,更正为
|
||||||
|
var m runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&m)
|
||||||
|
fmt.Printf("%d Kb\n", m.Alloc / 1024)
|
||||||
```
|
```
|
||||||
|
|
||||||
上面的程序会给出已分配内存的总量,单位是 Kb。进一步的测量参考 [文档页面](http://golang.org/pkg/runtime/#MemStatsType)。
|
上面的程序会给出已分配内存的总量,单位是 Kb。进一步的测量参考 [文档页面](http://golang.org/pkg/runtime/#MemStatsType)。
|
||||||
|
68
eBook/11.11.md
Normal file
68
eBook/11.11.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# 11.11 Printf和反射
|
||||||
|
|
||||||
|
在Go语言的标准库中,前几节所述的反射的功能被大量地使用。举个例子,fmt包中的Printf(以及其他格式化输出函数)都会使用反射来分析它的`...`参数。
|
||||||
|
|
||||||
|
Printf的函数声明为:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Printf(format string, args ... interface{}) (n int, err error)
|
||||||
|
```
|
||||||
|
|
||||||
|
Printf中的`...`参数为空接口类型。Printf使用反射包来解析这个参数列表。所以,Printf能够知道它每个参数的类型。因此格式化字符串中只有%d而没有%u和%ld,因为它知道这个参数是unsigned还是long。这也是为什么Print和Println在没有格式字符串的情况下还能如此漂亮地输出。
|
||||||
|
|
||||||
|
为了让大家更加具体地了解Printf中的反射,我们实现了一个简单的通用输出函数。其中使用了type-switch来推导参数类型,并根据类型来输出每个参数的值(这里用了10.7节中练习10.13的部分代码)
|
||||||
|
|
||||||
|
示例 11.15 print.go:
|
||||||
|
```go
|
||||||
|
// print.go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Stringer interface {
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Celsius float64
|
||||||
|
|
||||||
|
func (c Celsius) String() string {
|
||||||
|
return strconv.FormatFloat(float64(c),'f', 1, 64) + " °C"
|
||||||
|
}
|
||||||
|
|
||||||
|
type Day int
|
||||||
|
|
||||||
|
var dayName = []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
|
||||||
|
|
||||||
|
func (day Day) String() string {
|
||||||
|
return dayName[day]
|
||||||
|
}
|
||||||
|
|
||||||
|
func print(args ...interface{}) {
|
||||||
|
for i, arg := range args {
|
||||||
|
if i > 0 {os.Stdout.WriteString(" ")}
|
||||||
|
switch a := arg.(type) { // type switch
|
||||||
|
case Stringer: os.Stdout.WriteString(a.String())
|
||||||
|
case int: os.Stdout.WriteString(strconv.Itoa(a))
|
||||||
|
case string: os.Stdout.WriteString(a)
|
||||||
|
// more types
|
||||||
|
default: os.Stdout.WriteString("???")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
print(Day(1), "was", Celsius(18.36)) // Tuesday was 18.4 °C
|
||||||
|
}
|
||||||
|
// Tuesday was 18.4 °C
|
||||||
|
```
|
||||||
|
|
||||||
|
在12.8节中我们将阐释fmt.Fprintf()是怎么运用同样的反射原则的。
|
||||||
|
|
||||||
|
## 链接
|
||||||
|
|
||||||
|
- [目录](directory.md)
|
||||||
|
- 上一节:[反射包](11.10.md)
|
||||||
|
- 下一节:[接口和动态类型](11.12.md)
|
Reference in New Issue
Block a user