mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-12-20 12:44:20 +08:00
修正半角标点符号
This commit is contained in:
@@ -38,11 +38,11 @@ struct{ bool; int16; float64 } // 2 words 3words
|
||||
|
||||
关于内存地址对齐算法的细节超出了本书的范围,也不是每一个结构体都需要担心这个问题,不过有效的包装可以使数据结构更加紧凑(译注:未来的Go语言编译器应该会默认优化结构体的顺序,当然应该也能够指定具体的内存布局,相同讨论请参考 [Issue10014](https://github.com/golang/go/issues/10014) ),内存使用率和性能都可能会受益。
|
||||
|
||||
`unsafe.Alignof` 函数返回对应参数的类型需要对齐的倍数. 和 Sizeof 类似, Alignof 也是返回一个常量表达式, 对应一个常量. 通常情况下布尔和数字类型需要对齐到它们本身的大小(最多8个字节), 其它的类型对齐到机器字大小.
|
||||
`unsafe.Alignof` 函数返回对应参数的类型需要对齐的倍数。和 Sizeof 类似, Alignof 也是返回一个常量表达式,对应一个常量。通常情况下布尔和数字类型需要对齐到它们本身的大小(最多8个字节),其它的类型对齐到机器字大小。
|
||||
|
||||
`unsafe.Offsetof` 函数的参数必须是一个字段 `x.f`, 然后返回 `f` 字段相对于 `x` 起始地址的偏移量, 包括可能的空洞.
|
||||
`unsafe.Offsetof` 函数的参数必须是一个字段 `x.f`,然后返回 `f` 字段相对于 `x` 起始地址的偏移量,包括可能的空洞。
|
||||
|
||||
图 13.1 显示了一个结构体变量 x 以及其在32位和64位机器上的典型的内存. 灰色区域是空洞.
|
||||
图 13.1 显示了一个结构体变量 x 以及其在32位和64位机器上的典型的内存。灰色区域是空洞。
|
||||
|
||||
```Go
|
||||
var x struct {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Go程序可能会遇到要访问C语言的某些硬件驱动函数的场景,或者是从一个C++语言实现的嵌入式数据库查询记录的场景,或者是使用Fortran语言实现的一些线性代数库的场景。C语言作为一个通用语言,很多库会选择提供一个C兼容的API,然后用其他不同的编程语言实现(译者:Go语言需要也应该拥抱这些巨大的代码遗产)。
|
||||
|
||||
在本节中,我们将构建一个简易的数据压缩程序,使用了一个Go语言自带的叫cgo的用于支援C语言函数调用的工具。这类工具一般被称为 *foreign-function interfaces* (简称ffi), 并且在类似工具中cgo也不是唯一的。SWIG( http://swig.org )是另一个类似的且被广泛使用的工具,SWIG提供了很多复杂特性以支援C++的特性,但SWIG并不是我们要讨论的主题。
|
||||
在本节中,我们将构建一个简易的数据压缩程序,使用了一个Go语言自带的叫cgo的用于支援C语言函数调用的工具。这类工具一般被称为 *foreign-function interfaces* (简称ffi),并且在类似工具中cgo也不是唯一的。SWIG(http://swig.org)是另一个类似的且被广泛使用的工具,SWIG提供了很多复杂特性以支援C++的特性,但SWIG并不是我们要讨论的主题。
|
||||
|
||||
在标准库的`compress/...`子包有很多流行的压缩算法的编码和解码实现,包括流行的LZW压缩算法(Unix的compress命令用的算法)和DEFLATE压缩算法(GNU gzip命令用的算法)。这些包的API的细节虽然有些差异,但是它们都提供了针对 io.Writer类型输出的压缩接口和提供了针对io.Reader类型输入的解压缩接口。例如:
|
||||
|
||||
@@ -37,7 +37,7 @@ bzip2压缩算法,是基于优雅的Burrows-Wheeler变换算法,运行速度
|
||||
// pointers to Go variables.
|
||||
```
|
||||
|
||||
要使用libbzip2,我们需要先构建一个bz_stream结构体,用于保持输入和输出缓存。然后有三个函数:BZ2_bzCompressInit用于初始化缓存,BZ2_bzCompress用于将输入缓存的数据压缩到输出缓存,BZ2_bzCompressEnd用于释放不需要的缓存。(目前不要担心包的具体结构, 这个例子的目的就是演示各个部分如何组合在一起的。)
|
||||
要使用libbzip2,我们需要先构建一个bz_stream结构体,用于保持输入和输出缓存。然后有三个函数:BZ2_bzCompressInit用于初始化缓存,BZ2_bzCompress用于将输入缓存的数据压缩到输出缓存,BZ2_bzCompressEnd用于释放不需要的缓存。(目前不要担心包的具体结构,这个例子的目的就是演示各个部分如何组合在一起的。)
|
||||
|
||||
我们可以在Go代码中直接调用BZ2_bzCompressInit和BZ2_bzCompressEnd,但是对于BZ2_bzCompress,我们将定义一个C语言的包装函数,用它完成真正的工作。下面是C代码,对应一个独立的文件。
|
||||
|
||||
@@ -204,7 +204,7 @@ $ ./bzipper < /usr/share/dict/words | bunzip2 | sha256sum
|
||||
126a4ef38493313edc50b86f90dfdaf7c59ec6c948451eac228f2f3a8ab1a6ed -
|
||||
```
|
||||
|
||||
我们演示了如何将一个C语言库链接到Go语言程序。相反, 将Go编译为静态库然后链接到C程序,或者将Go程序编译为动态库然后在C程序中动态加载也都是可行的(译注:在Go1.5中,Windows系统的Go语言实现并不支持生成C语言动态库或静态库的特性。不过好消息是,目前已经有人在尝试解决这个问题,具体请访问 [Issue11058](https://github.com/golang/go/issues/11058) )。这里我们只展示的cgo很小的一些方面,更多的关于内存管理、指针、回调函数、中断信号处理、字符串、errno处理、终结器,以及goroutines和系统线程的关系等,有很多细节可以讨论。特别是如何将Go语言的指针传入C函数的规则也是异常复杂的(译注:简单来说,要传入C函数的Go指针指向的数据本身不能包含指针或其他引用类型;并且C函数在返回后不能继续持有Go指针;并且在C函数返回之前,Go指针是被锁定的,不能导致对应指针数据被移动或栈的调整),部分的原因在13.2节有讨论到,但是在Go1.5中还没有被明确(译注:Go1.6将会明确cgo中的指针使用规则)。如果要进一步阅读,可以从 https://golang.org/cmd/cgo 开始。
|
||||
我们演示了如何将一个C语言库链接到Go语言程序。相反,将Go编译为静态库然后链接到C程序,或者将Go程序编译为动态库然后在C程序中动态加载也都是可行的(译注:在Go1.5中,Windows系统的Go语言实现并不支持生成C语言动态库或静态库的特性。不过好消息是,目前已经有人在尝试解决这个问题,具体请访问 [Issue11058](https://github.com/golang/go/issues/11058) )。这里我们只展示的cgo很小的一些方面,更多的关于内存管理、指针、回调函数、中断信号处理、字符串、errno处理、终结器,以及goroutines和系统线程的关系等,有很多细节可以讨论。特别是如何将Go语言的指针传入C函数的规则也是异常复杂的(译注:简单来说,要传入C函数的Go指针指向的数据本身不能包含指针或其他引用类型;并且C函数在返回后不能继续持有Go指针;并且在C函数返回之前,Go指针是被锁定的,不能导致对应指针数据被移动或栈的调整),部分的原因在13.2节有讨论到,但是在Go1.5中还没有被明确(译注:Go1.6将会明确cgo中的指针使用规则)。如果要进一步阅读,可以从 https://golang.org/cmd/cgo 开始。
|
||||
|
||||
**练习 13.3:** 使用sync.Mutex以保证bzip2.writer在多个goroutines中被并发调用是安全的。
|
||||
|
||||
|
||||
@@ -16,5 +16,4 @@ Go语言的实现刻意隐藏了很多底层细节。我们无法知道一个结
|
||||
|
||||
要注意的是,unsafe包是一个采用特殊方式实现的包。虽然它可以和普通包一样的导入和使用,但它实际上是由编译器实现的。它提供了一些访问语言内部特性的方法,特别是内存布局相关的细节。将这些特性封装到一个独立的包中,是为在极少数情况下需要使用的时候,同时引起人们的注意(译注:因为看包的名字就知道使用unsafe包是不安全的)。此外,有一些环境因为安全的因素可能限制这个包的使用。
|
||||
|
||||
不过unsafe包被广泛地用于比较低级的包, 例如runtime、os、syscall还有net包等,因为它们需要和操作系统密切配合,但是对于普通的程序一般是不需要使用unsafe包的。
|
||||
|
||||
不过unsafe包被广泛地用于比较低级的包,例如runtime、os、syscall还有net包等,因为它们需要和操作系统密切配合,但是对于普通的程序一般是不需要使用unsafe包的。
|
||||
|
||||
Reference in New Issue
Block a user