mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2024-10-11 14:25:05 +00:00
fix: typo
This commit is contained in:
parent
e04e007edb
commit
b822eda268
@ -2,5 +2,5 @@
|
||||
|
||||
- 柴树杉(Github [@chai2010](https://github.com/chai2010); Twitter [@chaishushan](https://twitter.com/chaishushan))Go语言代码贡献者,Dart语言和WebAssembly等技术爱好者,著有[《WebAssembly标准入门》](https://github.com/chai2010/awesome-wasm-zh/blob/master/webassembly-primer.md)等书。
|
||||
|
||||
- 曹春晖(Gtihub [@cch123](https://github.com/cch123))在 web 领域工作多年,开源爱好者。对大型网站系统的架构和相关工具的实现很感兴趣,并且有一些研究成果。目前在滴滴平台技术部工作。
|
||||
- 曹春晖(Github [@cch123](https://github.com/cch123))在 web 领域工作多年,开源爱好者。对大型网站系统的架构和相关工具的实现很感兴趣,并且有一些研究成果。目前在滴滴平台技术部工作。
|
||||
|
||||
|
@ -233,7 +233,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
当`<-done`执行时,必然要求`done <- 1`也已经执行。根据同一个Gorouine依然满足顺序一致性规则,我们可以判断当`done <- 1`执行时,`println("你好, 世界")`语句必然已经执行完成了。因此,现在的程序确保可以正常打印结果。
|
||||
当`<-done`执行时,必然要求`done <- 1`也已经执行。根据同一个Goroutine依然满足顺序一致性规则,我们可以判断当`done <- 1`执行时,`println("你好, 世界")`语句必然已经执行完成了。因此,现在的程序确保可以正常打印结果。
|
||||
|
||||
当然,通过`sync.Mutex`互斥量也是可以实现同步的:
|
||||
|
||||
|
@ -194,7 +194,7 @@ func main() {
|
||||
|
||||
```go
|
||||
for i, e := range err.(errors.Error).Wraped() {
|
||||
fmt.Printf("wraped(%d): %v\n", i, e)
|
||||
fmt.Printf("wrapped(%d): %v\n", i, e)
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -108,7 +108,7 @@ import "C"
|
||||
// #cgo !windows LDFLAGS: -lm
|
||||
```
|
||||
|
||||
其中在windows平台下,编译前会预定义X86宏为1;在非widnows平台下,在链接阶段会要求链接math数学库。这种用法对于在不同平台下只有少数编译选项差异的场景比较适用。
|
||||
其中在windows平台下,编译前会预定义X86宏为1;在非windows平台下,在链接阶段会要求链接math数学库。这种用法对于在不同平台下只有少数编译选项差异的场景比较适用。
|
||||
|
||||
如果在不同的系统下cgo对应着不同的c代码,我们可以先使用`#cgo`指令定义不同的C语言的宏,然后通过宏来区分不同的代码:
|
||||
|
||||
|
@ -21,7 +21,7 @@ void* makeslice(size_t memsize) {
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func makeByteSlize(n int) []byte {
|
||||
func makeByteSlice(n int) []byte {
|
||||
p := C.makeslice(C.size_t(n))
|
||||
return ((*[1 << 31]byte)(p))[0:n:n]
|
||||
}
|
||||
@ -31,14 +31,14 @@ func freeByteSlice(p []byte) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
s := makeByteSlize(1<<32+1)
|
||||
s := makeByteSlice(1<<32+1)
|
||||
s[len(s)-1] = 255
|
||||
print(s[len(s)-1])
|
||||
freeByteSlice(s)
|
||||
}
|
||||
```
|
||||
|
||||
例子中我们通过makeByteSlize来创建大于4G内存大小的切片,从而绕过了Go语言实现的限制(需要代码验证)。而freeByteSlice辅助函数则用于释放从C语言函数创建的切片。
|
||||
例子中我们通过makeByteSlice来创建大于4G内存大小的切片,从而绕过了Go语言实现的限制(需要代码验证)。而freeByteSlice辅助函数则用于释放从C语言函数创建的切片。
|
||||
|
||||
因为C语言内存空间是稳定的,基于C语言内存构造的切片也是绝对稳定的,不会因为Go语言栈的变化而被移动。
|
||||
|
||||
@ -46,7 +46,7 @@ func main() {
|
||||
|
||||
cgo之所以存在的一大因素是为了方便在Go语言中接纳吸收过去几十年来使用C/C++语言软件构建的大量的软件资源。C/C++很多库都是需要通过指针直接处理传入的内存数据的,因此cgo中也有很多需要将Go内存传入C语言函数的应用场景。
|
||||
|
||||
假设一个极端场景:我们将一块位于某goroutinue的栈上的Go语言内存传入了C语言函数后,在此C语言函数执行期间,此goroutinue的栈因为空间不足的原因发生了扩展,也就是导致了原来的Go语言内存被移动到了新的位置。但是此时此刻C语言函数并不知道该Go语言内存已经移动了位置,仍然用之前的地址来操作该内存——这将将导致内存越界。以上是一个推论(真实情况有些差异),也就是说C访问传入的Go内存可能是不安全的!
|
||||
假设一个极端场景:我们将一块位于某goroutine的栈上的Go语言内存传入了C语言函数后,在此C语言函数执行期间,此goroutinue的栈因为空间不足的原因发生了扩展,也就是导致了原来的Go语言内存被移动到了新的位置。但是此时此刻C语言函数并不知道该Go语言内存已经移动了位置,仍然用之前的地址来操作该内存——这将将导致内存越界。以上是一个推论(真实情况有些差异),也就是说C访问传入的Go内存可能是不安全的!
|
||||
|
||||
当然有RPC远程过程调用的经验的用户可能会考虑通过完全传值的方式处理:借助C语言内存稳定的特性,在C语言空间先开辟同样大小的内存,然后将Go的内存填充到C的内存空间;返回的内存也是如此处理。下面的例子是这种思路的具体实现:
|
||||
|
||||
|
@ -156,7 +156,7 @@ var g_goid_offset = func() int64 {
|
||||
return off
|
||||
}
|
||||
}
|
||||
panic("unsupport go verion:"+goversion)
|
||||
panic("unsupported go version:"+goversion)
|
||||
}()
|
||||
```
|
||||
|
||||
|
@ -62,7 +62,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
其中redentials.NewClientTLSFromFile是构造客户端用的证书对象,第一个参数是服务器的证书文件,第二个参数是签发证书的服务器的名字。然后通过grpc.WithTransportCredentials(creds)将证书对象转为参数选项传人grpc.Dial函数。
|
||||
其中credentials.NewClientTLSFromFile是构造客户端用的证书对象,第一个参数是服务器的证书文件,第二个参数是签发证书的服务器的名字。然后通过grpc.WithTransportCredentials(creds)将证书对象转为参数选项传人grpc.Dial函数。
|
||||
|
||||
以上这种方式,需要提前将服务器的证书告知客户端,这样客户端在链接服务器时才能进行对服务器证书认证。在复杂的网络环境中,服务器证书的传输本身也是一个非常危险的问题。如果在中间某个环节,服务器证书被监听或替换那么对服务器的认证也将不再可靠。
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user