1
0
mirror of https://github.com/chai2010/advanced-go-programming-book.git synced 2025-05-23 20:02:22 +00:00

Merge branch 'master' into master

This commit is contained in:
Xargin 2019-07-11 01:13:15 +08:00 committed by GitHub
commit 9c475a3c17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 51 additions and 29 deletions

BIN
163study-go-master.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
A20181610.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

View File

@ -27,8 +27,9 @@ server:
go run server.go
cover:
convert -resize 1800x2360! cover.png cover.jpg
convert -resize 200x262! cover.png cover_small.jpg
convert A20181610.jpg cover.png
convert -resize 1800x2360! A20181610.jpg cover.jpg
convert -resize 200x262! A20181610.jpg cover_small.jpg
# https://chai2010.cn/advanced-go-programming-book

View File

@ -1,5 +1,7 @@
# Go语言高级编程 (Advanced Go Programming)
*推广: 欢迎关注 [网易云课堂·光谷码农课堂](https://study.163.com/provider/480000001914454/index.htm)*
*推广: [《WebAssembly标准入门》开始预售了欢迎关注](https://github.com/chai2010/awesome-wasm-zh/blob/master/webassembly-primer.md)([京东购买](https://item.jd.com/12499372.html))*
*推广: 欢迎关注 [光谷码农·每日新闻](https://guanggu-coder.cn/)*
@ -15,6 +17,11 @@
- 网址https://github.com/chai2010/advanced-go-programming-book
- Star历史https://starcharts.herokuapp.com/chai2010/advanced-go-programming-book.svg
购买链接:
- 京东https://item.m.jd.com/product/12647494.html
- 异步https://www.epubit.com/book/detail/40090
## 在线阅读
- [SUMMARY.md](SUMMARY.md)
@ -25,6 +32,8 @@
https://study.163.com/provider/480000001914454/index.htm
![](163study-go-master.jpg)
## 相关文章
1. [GopherChina 2019大会推荐书单来啦](https://zhuanlan.zhihu.com/p/63910336)
@ -38,14 +47,12 @@ https://study.163.com/provider/480000001914454/index.htm
1. [Go语言并发编程](https://talks.godoc.org/github.com/chai2010/awesome-go-zh/chai2010/chai2010-golang-concurrency.slide) - [chai2010](https://github.com/chai2010/awesome-go-zh/tree/master/chai2010) 武汉·光谷猫友会 2018/09/16, [整理01](https://mp.weixin.qq.com/s/UaY9gJU85dq-dXlOhLYY1Q)/[整理02](https://mp.weixin.qq.com/s/_aKNO-H11GEDA-l0rycfQQ)
1. 深入CGO编程: https://github.com/chai2010/gopherchina2018-cgo-talk
## 加入微信群
![](https://chai2010.cn/static-images/weixin-golang.jpg)
## 关注微信公众号(光谷码农/guanggu-coder)
![](https://chai2010.cn/advanced-go-programming-book/weixin-guanggu-coder-logo.png)
**加入微信群:公众号底部菜单扫码进群。**
## 开发者头条号
https://toutiao.io/subjects/318517

View File

@ -183,7 +183,7 @@ func CloseFile(f *File) error {
}
// 读文件数据
func ReadFile(f *File, int64 offset, data []byte) int {
func ReadFile(f *File, offset int64, data []byte) int {
// ...
}
```
@ -199,7 +199,7 @@ func (f *File) CloseFile() error {
}
// 读文件数据
func (f *File) ReadFile(int64 offset, data []byte) int {
func (f *File) ReadFile(offset int64, data []byte) int {
// ...
}
```
@ -213,7 +213,7 @@ func (f *File) Close() error {
}
// 读文件数据
func (f *File) Read(int64 offset, data []byte) int {
func (f *File) Read(offset int64, data []byte) int {
// ...
}
```
@ -228,7 +228,7 @@ func (f *File) Read(int64 offset, data []byte) int {
var CloseFile = (*File).Close
// 不依赖具体的文件对象
// func ReadFile(f *File, int64 offset, data []byte) int
// func ReadFile(f *File, offset int64, data []byte) int
var ReadFile = (*File).Read
// 文件处理
@ -245,13 +245,13 @@ f, _ := OpenFile("foo.dat")
// 绑定到了 f 对象
// func Close() error
var Close = func Close() error {
var Close = func() error {
return (*File).Close(f)
}
// 绑定到了 f 对象
// func Read(int64 offset, data []byte) int
var Read = func Read(int64 offset, data []byte) int {
// func Read(offset int64, data []byte) int
var Read = func(offset int64, data []byte) int {
return (*File).Read(f, offset, data)
}
@ -271,7 +271,7 @@ f, _ := OpenFile("foo.dat")
var Close = f.Close
// 方法值: 绑定到了 f 对象
// func Read(int64 offset, data []byte) int
// func Read(offset int64, data []byte) int
var Read = f.Read
// 文件处理

View File

@ -322,12 +322,15 @@ type SliceHeader struct {
```go
/*
static char arr[10];
static char *s = "Hello";
#include <string.h>
char arr[10];
char *s = "Hello";
*/
import "C"
import "fmt"
import (
"reflect"
"unsafe"
)
func main() {
// 通过 reflect.SliceHeader 转换
var arr0 []byte
@ -345,7 +348,7 @@ func main() {
s0Hdr.Len = int(C.strlen(C.s))
sLen := int(C.strlen(C.s))
s1 := string((*[31]byte)(unsafe.Pointer(&C.s[0]))[:sLen:sLen])
s1 := string((*[31]byte)(unsafe.Pointer(C.s))[:sLen:sLen])
}
```

View File

@ -162,7 +162,7 @@ func main() {}
CGO的语法细节不在赘述。为了在C语言中使用sum函数我们需要将Go代码编译为一个C静态库
```
$ go build -buildmode=c-archive -o sum.a sum.go
$ go build -buildmode=c-archive -o sum.a main.go
```
如果没有错误的话,以上编译命令将生成一个`sum.a`静态库和`sum.h`头文件。其中`sum.h`头文件将包含sum函数的声明静态库中将包含sum函数的实现。

View File

@ -4,7 +4,7 @@
## 5.5.1 从 database/sql 讲起
Go官方提供了`database/sql`给用户进行和数据库打交道的工作,实际上`database/sql`库就只是提供了一套操作数据库的接口和规范例如抽象好的SQL预处理prepare连接池管理数据绑定事务错误处理等等。官方并没有提供具体某种数据库实现的协议支持。
Go官方提供了`database/sql`来给用户进行和数据库打交道的工作,`database/sql`库实际只提供了一套操作数据库的接口和规范例如抽象好的SQL预处理prepare连接池管理数据绑定事务错误处理等等。官方并没有提供具体某种数据库实现的协议支持。
和具体的数据库例如MySQL打交道还需要再引入MySQL的驱动像下面这样
@ -19,7 +19,7 @@ db, err := sql.Open("mysql", "user:password@/dbname")
import _ "github.com/go-sql-driver/mysql"
```
一句import实际上是调用了`mysql`包的`init`函数,做的事情也很简单:
条import语句会调用了`mysql`包的`init`函数,做的事情也很简单:
```go
func init() {
@ -27,7 +27,7 @@ func init() {
}
```
`sql`包的 全局`map`里把`mysql`这个名字的`driver`注册上。实际上`Driver``sql`包中是一个接口:
`sql`包的全局`map`里把`mysql`这个名字的`driver`注册上。`Driver``sql`包中是一个接口:
```go
type Driver interface {
@ -35,7 +35,7 @@ type Driver interface {
}
```
调用`sql.Open()`返回的`db`对象实际上就是这里的`Conn`
调用`sql.Open()`返回的`db`对象就是这里的`Conn`
```go
type Conn interface {
@ -45,7 +45,7 @@ type Conn interface {
}
```
也是一个接口。实际上如果你仔细地查看`database/sql/driver/driver.go`的代码会发现,这个文件里所有的成员全都是接口,对这些类型进行操作,实际上还是会调用具体的`driver`里的方法。
也是一个接口。如果你仔细地查看`database/sql/driver/driver.go`的代码会发现,这个文件里所有的成员全都是接口,对这些类型进行操作,还是会调用具体的`driver`里的方法。
从用户的角度来讲,在使用`database/sql`包的过程中,你能够使用的也就是这些接口里提供的函数。来看一个使用`database/sql``go-sql-driver/mysql`的完整的例子:
@ -114,7 +114,7 @@ func main() {
从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。
```
最为常见的ORM实际上做的是从db到程序的类或结构体这样的映射。所以你手边的程序可能是从MySQL的表映射你的程序内的类。我们可以先来看看其它的程序语言里的ORM写起来是怎么样的感觉
最为常见的ORM做的是从db到程序的类或结构体这样的映射。所以你手边的程序可能是从MySQL的表映射你的程序内的类。我们可以先来看看其它的程序语言里的ORM写起来是怎么样的感觉
```python
>>> from blog.models import Blog
@ -122,7 +122,7 @@ func main() {
>>> b.save()
```
完全没有数据库的痕迹没错ORM的目的就是屏蔽掉DB层实际上很多语言的ORM只要把你的类或结构体定义好再用特定的语法将结构体之间的一对一或者一对多关系表达出来。那么任务就完成了。然后你就可以对这些映射好了数据库表的对象进行各种操作例如savecreateretrievedelete。至于ORM在背地里做了什么阴险的勾当你是不一定清楚的。使用ORM的时候我们往往比较容易有一种忘记了数据库的直观感受。举个例子我们有个需求向用户展示最新的商品列表我们再假设商品和商家是1:1的关联关系我们就很容易写出像下面这样的代码
完全没有数据库的痕迹,没错ORM的目的就是屏蔽掉DB层很多语言的ORM只要把你的类或结构体定义好再用特定的语法将结构体之间的一对一或者一对多关系表达出来。那么任务就完成了。然后你就可以对这些映射好了数据库表的对象进行各种操作例如savecreateretrievedelete。至于ORM在背地里做了什么阴险的勾当你是不一定清楚的。使用ORM的时候我们往往比较容易有一种忘记了数据库的直观感受。举个例子我们有个需求向用户展示最新的商品列表我们再假设商品和商家是1:1的关联关系我们就很容易写出像下面这样的代码
```python
# 伪代码
@ -134,7 +134,7 @@ for product in productList {
当然了我们不能批判这样写代码的程序员是偷懒的程序员。因为ORM一类的工具在出发点上就是屏蔽sql让我们对数据库的操作更接近于人类的思维方式。这样很多只接触过ORM而且又是刚入行的程序员就很容易写出上面这样的代码。
这样的代码将对数据库的读请求放大了N倍。也就是说如果你的商品列表有15个SKU那么每次用户打开这个页面至少需要执行1查询商品列表+ 15查询相关的商铺信息次查询。这里N是16。如果你的列表页很大比如说有600个条目那么你就至少要执行1+600次查询。如果说你的数据库能够承受的最大的简单查询是12万QPS而上述这样的查询正好是你最常用的查询的话实际上你能对外提供的服务能力是多少呢是200 qps互联网系统的忌讳之一就是这种无端的读放大。
这样的代码将对数据库的读请求放大了N倍。也就是说如果你的商品列表有15个SKU那么每次用户打开这个页面至少需要执行1查询商品列表+ 15查询相关的商铺信息次查询。这里N是16。如果你的列表页很大比如说有600个条目那么你就至少要执行1+600次查询。如果说你的数据库能够承受的最大的简单查询是12万QPS而上述这样的查询正好是你最常用的查询的话你能对外提供的服务能力是多少呢是200 qps互联网系统的忌讳之一就是这种无端的读放大。
当然你也可以说这不是ORM的问题如果你手写sql你还是可能会写出差不多的程序那么再来看两个demo
@ -143,7 +143,7 @@ o := orm.NewOrm()
num, err := o.QueryTable("cardgroup").Filter("Cards__Card__Name", cardName).All(&cardgroups)
```
很多ORM都提供了这种Filter类型的查询方式不过实际上在某些ORM背后甚至隐藏了非常难以察觉的细节比如生成的SQL语句会自动`limit 1000`
很多ORM都提供了这种Filter类型的查询方式不过在某些ORM背后可能隐藏了非常难以察觉的细节比如生成的SQL语句会自动`limit 1000`
也许喜欢ORM的读者读到这里会反驳了你是没有认真阅读文档就瞎写。是的尽管这些ORM工具在文档里说明了All查询在不显式地指定Limit的话会自动limit 1000但对于很多没有阅读过文档或者看过ORM源码的人这依然是一个非常难以察觉的“魔鬼”细节。喜欢强类型语言的人一般都不喜欢语言隐式地去做什么事情例如各种语言在赋值操作时进行的隐式类型转换然后又在转换中丢失了精度的勾当一定让你非常的头疼。所以一个程序库背地里做的事情还是越少越好如果一定要做那也一定要在显眼的地方做。比如上面的例子去掉这种默认的自作聪明的行为或者要求用户强制传入limit参数都是更好的选择。

BIN
cover.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 195 KiB

BIN
cover.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 845 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -8,16 +8,27 @@
- 作者曹春晖Github [@cch123](https://github.com/cch123)
- 网址https://github.com/chai2010/advanced-go-programming-book
购买链接:
- https://www.epubit.com/book/detail/40090
## 在线阅读
- https://chai2010.cn/advanced-go-programming-book/
- https://www.gitbook.com/book/chai2010/advanced-go-programming-book/
## 关注微信公众号 (guanggu-coder)
![](weixin-guanggu-coder-logo.png)
## 网易云课堂·光谷码农课堂
https://study.163.com/provider/480000001914454/index.htm
![](163study-go-master.jpg)
## 版权声明
[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/)。