fix typo and optimize.

Change-Id: I7b6938936231fd722814984678ffa30402539fd9
This commit is contained in:
fuyc
2016-08-11 17:08:38 +08:00
parent ed57986ea7
commit 8fda418f3a
33 changed files with 128 additions and 126 deletions

View File

@@ -27,7 +27,7 @@ func | 1个机器字
chan | 1个机器字
interface | 2个机器字(type,value)
Go语言的规范并没有要求一个字段的声明顺序和内存中的顺序是一致的所以理论上一个编译器可以随意地重新排列每个字段的内存位置然在写作本书的时候编译器还没有这么做。下面的三个结构体虽然有着相同的字段但是第一种写法比另外的两个需要多50%的内存。
Go语言的规范并没有要求一个字段的声明顺序和内存中的顺序是一致的所以理论上一个编译器可以随意地重新排列每个字段的内存位置然在写作本书的时候编译器还没有这么做。下面的三个结构体虽然有着相同的字段但是第一种写法比另外的两个需要多50%的内存。
```Go
// 64-bit 32-bit

View File

@@ -56,7 +56,7 @@ pT := uintptr(unsafe.Pointer(new(T))) // 提示: 错误!
在编写本文时还没有清晰的原则来指引Go程序员什么样的unsafe.Pointer和uintptr的转换是不安全的参考 [Issue7192](https://github.com/golang/go/issues/7192) . 译注: 该问题已经关闭因此我们强烈建议按照最坏的方式处理。将所有包含变量地址的uintptr类型变量当作BUG处理同时减少不必要的unsafe.Pointer类型到uintptr类型的转换。在第一个例子中有三个转换——字段偏移量到uintptr的转换和转回unsafe.Pointer类型的操作——所有的转换全在一个表达式完成。
当调用一个库函数并且返回的是uintptr类型地址时译注普通方法实现的函数尽量不要返回该类型。下面例子是reflect包的函数reflect包和unsafe包一样都是采用特殊技术实现的编译器可能给它们开了后门比如下面反射包中的相关函数返回的结果应该立即转换为unsafe.Pointer以确保指针指向的是相同的变量。
当调用一个库函数并且返回的是uintptr类型地址时译注普通方法实现的函数尽量不要返回该类型。下面例子是reflect包的函数reflect包和unsafe包一样都是采用特殊技术实现的编译器可能给它们开了后门比如下面反射包中的相关函数返回的结果应该立即转换为unsafe.Pointer以确保指针指向的是相同的变量。
```Go
package reflect

View File

@@ -101,7 +101,7 @@ func NewWriter(out io.Writer) io.WriteCloser {
}
```
在预处理过程中cgo工具为生成一个临时包用于包含所有在Go语言中访问的C语言的函数或类型。例如C.bz_stream和C.BZ2_bzCompressInit。cgo工具通过以某种特殊的方式调用本地的C编译器来发现在Go源文件导入声明前的注释中包含的C头文件中的内容译注`import "C"`语句前挨着的注释是对应cgo的特殊语法对应必要的构建参数选项和C语言代码
在预处理过程中cgo工具为生成一个临时包用于包含所有在Go语言中访问的C语言的函数或类型。例如C.bz_stream和C.BZ2_bzCompressInit。cgo工具通过以某种特殊的方式调用本地的C编译器来发现在Go源文件导入声明前的注释中包含的C头文件中的内容译注`import "C"`语句前挨着的注释是对应cgo的特殊语法对应必要的构建参数选项和C语言代码
在cgo注释中还可以包含#cgo指令用于给C语言工具链指定特殊的参数。例如CFLAGS和LDFLAGS分别对应传给C语言编译器的编译参数和链接器参数使它们可以特定目录找到bzlib.h头文件和libbz2.a库文件。这个例子假设你已经在/usr目录成功安装了bzip2库。如果bzip2库是安装在不同的位置你需要更新这些参数译注这里有一个从纯C代码生成的cgo绑定不依赖bzip2静态库和操作系统的具体环境具体请访问 https://github.com/chai2010/bzip2 )。

View File

@@ -1,6 +1,6 @@
# 第13章 底层编程
Go语言的设计包含了诸多安全策略限制了可能导致程序运行出现错误的用法。编译时类型检查检查可以发现大多数类型不匹配的操作例如两个字符串做减法的错误。字符串、map、slice和chan等所有的内置类型都有严格的类型转换规则。
Go语言的设计包含了诸多安全策略限制了可能导致程序运行出的用法。编译时类型检查可以发现大多数类型不匹配的操作例如两个字符串做减法的错误。字符串、map、slice和chan等所有的内置类型都有严格的类型转换规则。
对于无法静态检测到的错误,例如数组访问越界或使用空指针,运行时动态检测可以保证程序在遇到问题的时候立即终止并打印相关的错误信息。自动内存管理(垃圾内存自动回收)可以消除大部分野指针和内存泄漏相关的问题。
@@ -8,11 +8,11 @@ Go语言的实现刻意隐藏了很多底层细节。我们无法知道一个结
总的来说Go语言的这些特性使得Go程序相比较低级的C语言来说更容易预测和理解程序也不容易崩溃。通过隐藏底层的实现细节也使得Go语言编写的程序具有高度的可移植性因为语言的语义在很大程度上是独立于任何编译器实现、操作系统和CPU系统结构的当然也不是完全绝对独立例如int等类型就依赖于CPU机器字的大小某些表达式求值的具体顺序还有编译器实现的一些额外的限制等
有时候我们可能会放弃使用部分语言特性而优先选择更好具有更好性能的方法例如需要与其他语言编写的库互操作或者用纯Go语言无法实现的某些函数。
有时候我们可能会放弃使用部分语言特性而优先选择具有更好性能的方法,例如需要与其他语言编写的库进行互操作或者用纯Go语言无法实现的某些函数。
在本章我们将展示如何使用unsafe包来摆脱Go语言规则带来的限制讲述如何创建C语言函数库的绑定以及如何进行系统调用。
本章提供的方法不应该轻易使用(译注:属于黑魔法,虽然可能功能很强大但是也容易误伤到自己。如果没有处理好细节它们可能导致各种不可预测的并且隐晦的错误甚至连有经验的的C语言程序员也无法理解这些错误。使用unsafe包的同时也放弃了Go语言保证与未来版本的兼容性的承诺因为它必然会有意无意中使用很多实现细节而这些实现的细节在未来的Go语言中很可能会被改变。
本章提供的方法不应该轻易使用译注属于黑魔法虽然功能很强大但是也容易误伤到自己。如果没有处理好细节它们可能导致各种不可预测的并且隐晦的错误甚至连有经验的的C语言程序员也无法理解这些错误。使用unsafe包的同时也放弃了Go语言保证与未来版本的兼容性的承诺因为它必然会有意无意中使用很多非公开的实现细节而这些实现的细节在未来的Go语言中很可能会被改变。
要注意的是unsafe包是一个采用特殊方式实现的包。虽然它可以和普通包一样的导入和使用但它实际上是由编译器实现的。它提供了一些访问语言内部特性的方法特别是内存布局相关的细节。将这些特性封装到一个独立的包中是为在极少数情况下需要使用的时候同时引起人们的注意译注因为看包的名字就知道使用unsafe包是不安全的。此外有一些环境因为安全的因素可能限制这个包的使用。