1
0
mirror of https://github.com/chai2010/advanced-go-programming-book.git synced 2025-05-24 04:22:22 +00:00
This commit is contained in:
chai2010 2018-12-17 17:30:54 +08:00
parent 8c25545f9d
commit 9ad62fe063
18 changed files with 174 additions and 133 deletions

View File

@ -11,10 +11,10 @@ Go语言中数组、字符串和切片三者是密切相关的数据结构。这
我们先看看数组有哪些定义方式:
```go
var a [3]int // 定义一个长度为3的int型数组, 元素全部为0
var b = [...]int{1, 2, 3} // 定义一个长度为3的int型数组, 元素为 1, 2, 3
var c = [...]int{2: 3, 1: 2} // 定义一个长度为3的int型数组, 元素为 0, 2, 3
var d = [...]int{1, 2, 4: 5, 6} // 定义一个长度为6的int型数组, 元素为 1, 2, 0, 0, 5, 6
var a [3]int // 定义长度为3的int型数组, 元素全部为0
var b = [...]int{1, 2, 3} // 定义长度为3的int型数组, 元素为 1, 2, 3
var c = [...]int{2: 3, 1: 2} // 定义长度为3的int型数组, 元素为 0, 2, 3
var d = [...]int{1, 2, 4: 5, 6} // 定义长度为6的int型数组, 元素为 1, 2, 0, 0, 5, 6
```
第一种方式是定义一个数组变量的最基本的方式,数组的长度明确指定,数组中的每个元素都以零值初始化。
@ -169,7 +169,9 @@ type StringHeader struct {
分析可以发现“Hello, world”字符串底层数据和以下数组是完全一致的
```go
var data = [...]byte{'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd'}
var data = [...]byte{
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd',
}
```
字符串虽然不是切片,但是支持切片操作,不同位置的切片底层也访问的同一块内存数据(因为字符串是只读的,相同的字符串面值常量通常是对应同一个字符串常量):
@ -202,7 +204,8 @@ fmt.Printf("%#v\n", []byte("Hello, 世界"))
输出的结果是:
```go
[]byte{0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0xe4, 0xb8, 0x96, 0xe7, 0x95, 0x8c}
[]byte{0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0xe4, 0xb8, 0x96, 0xe7, \
0x95, 0x8c}
```
分析可以发现`0xe4, 0xb8, 0x96`对应中文“世”,`0xe7, 0x95, 0x8c`对应中文“界”。我们也可以在字符串面值中直指定UTF8编码后的值源文件中全部是ASCII码可以避免出现多字节的字符

View File

@ -384,10 +384,10 @@ Go语言中对于基础类型非接口类型不支持隐式的转换
```go
var (
a io.ReadCloser = (*os.File)(f) // 隐式转换, *os.File 类型满足 io.ReadCloser 接口
b io.Reader = a // 隐式转换, io.ReadCloser 满足 io.Reader 接口
c io.Closer = a // 隐式转换, io.ReadCloser 满足 io.Closer 接口
d io.Reader = c.(io.Reader) // 显式转换, io.Closer 显式满足 io.Reader 接口
a io.ReadCloser = (*os.File)(f) // 隐式转换, *os.File 满足 io.ReadCloser 接口
b io.Reader = a // 隐式转换, io.ReadCloser 满足 io.Reader 接口
c io.Closer = a // 隐式转换, io.ReadCloser 满足 io.Closer 接口
d io.Reader = c.(io.Reader) // 显式转换, io.Closer 不满足 io.Reader 接口
)
```
@ -491,7 +491,8 @@ type Plugin interface {
// code generation begins.
Init(g *Generator)
// Generate produces the code generated by the plugin for this file,
// except for the imports, by calling the generator's methods P, In, and Out.
// except for the imports, by calling the generator's methods
// P, In, and Out.
Generate(file *FileDescriptor)
// GenerateImports produces the import declarations for this file.
// It is called after Generate.

View File

@ -267,7 +267,9 @@ func (p *Publisher) Close() {
}
// 发送主题,可以容忍一定的超时
func (p *Publisher) sendTopic(sub subscriber, topic topicFunc, v interface{}, wg *sync.WaitGroup) {
func (p *Publisher) sendTopic(
sub subscriber, topic topicFunc, v interface{}, wg *sync.WaitGroup,
) {
defer wg.Done()
if topic != nil && !topic(v) {
return

View File

@ -422,7 +422,7 @@ func main {
}
}()
...
// ...
}
```

View File

@ -274,7 +274,9 @@ main._cgoexpwrap_cfb3840e3af2_getGoPtr(0xc420016078)
main._Cfunc_Main()
command-line-arguments/_obj/_cgo_gotypes.go:43 +0x41
main.main()
/Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/return-go-ptr/main.go:17 +0x20
/Users/chai/go/src/github.com/chai2010 \
/advanced-go-programming-book/examples/ch2-xx \
/return-go-ptr/main.go:17 +0x20
exit status 2
```

View File

@ -238,9 +238,12 @@ Goroutine 1:
(dlv) goroutines
[4 goroutines]
* Goroutine 1 - User: ./main.go:10 main.main (0x10aea33) (thread 101686)
Goroutine 2 - User: /usr/local/go/src/runtime/proc.go:292 runtime.gopark (0x102c189)
Goroutine 3 - User: /usr/local/go/src/runtime/proc.go:292 runtime.gopark (0x102c189)
Goroutine 4 - User: /usr/local/go/src/runtime/proc.go:292 runtime.gopark (0x102c189)
Goroutine 2 - User: /usr/local/go/src/runtime/proc.go:292 \
runtime.gopark (0x102c189)
Goroutine 3 - User: /usr/local/go/src/runtime/proc.go:292 \
runtime.gopark (0x102c189)
Goroutine 4 - User: /usr/local/go/src/runtime/proc.go:292 \
runtime.gopark (0x102c189)
(dlv)
```
@ -292,15 +295,15 @@ Breakpoint 1 set at 0x105011f for main.main() ./main.go:3
> main.main() ./main.go:3 (hits goroutine(1):1 total:1) (PC: 0x105011f)
1: package main
2:
=> 3: func main() { asmSayHello() }
=>3: func main() { asmSayHello() }
4:
5: func asmSayHello()
(dlv) disassemble
TEXT main.main(SB) /path/to/pkg/main.go
main.go:3 0x1050110 65488b0c25a0080000 mov rcx, qword ptr gs:[0x8a0]
main.go:3 0x1050119 483b6110 cmp rsp, qword ptr [rcx+0x10]
main.go:3 0x1050110 65488b0c25a0080000 mov rcx, qword ptr g [0x8a0]
main.go:3 0x1050119 483b6110 cmp rsp, qword ptr [r +0x10]
main.go:3 0x105011d 761a jbe 0x1050139
=> main.go:3 0x105011f* 4883ec08 sub rsp, 0x8
=>main.go:3 0x105011f* 4883ec08 sub rsp, 0x8
main.go:3 0x1050123 48892c24 mov qword ptr [rsp], rbp
main.go:3 0x1050127 488d2c24 lea rbp, ptr [rsp]
main.go:3 0x105012b e880000000 call $main.asmSayHello

View File

@ -318,7 +318,8 @@ RPC的服务架设在“/jsonrpc”路径在处理函数中基于http.Respons
模拟一次RPC调用的过程就是向该链接发送一个json字符串
```
$ curl localhost:1234/jsonrpc -X POST --data '{"method":"HelloService.Hello","params":["hello"],"id":0}'
$ curl localhost:1234/jsonrpc -X POST \
--data '{"method":"HelloService.Hello","params":["hello"],"id":0}'
```
返回的结果依然是json字符串

View File

@ -262,7 +262,9 @@ type ServiceMethodSpec struct {
然后我们新建一个buildServiceSpec方法用来解析每个服务的ServiceSpec元信息
```go
func (p *netrpcPlugin) buildServiceSpec(svc *descriptor.ServiceDescriptorProto) *ServiceSpec {
func (p *netrpcPlugin) buildServiceSpec(
svc *descriptor.ServiceDescriptorProto,
) *ServiceSpec {
spec := &ServiceSpec{
ServiceName: generator.CamelCase(svc.GetName()),
}

View File

@ -7,7 +7,10 @@
Go语言的RPC库最简单的使用方式是通过`Client.Call`方法进行同步阻塞调用,该方法的实现如下:
```go
func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error {
func (client *Client) Call(
serviceMethod string, args interface{},
reply interface{},
) error {
call := <-client.Go(serviceMethod, args, reply, make(chan *Call, 1)).Done
return call.Error
}
@ -39,7 +42,11 @@ func doClientWork(client *rpc.Client) {
执行异步调用的`Client.Go`方法实现如下:
```go
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
func (client *Client) Go(
serviceMethod string, args interface{},
reply interface{},
done chan *Call,
) *Call {
call := new(Call)
call.ServiceMethod = serviceMethod
call.Args = args
@ -164,7 +171,10 @@ func doClientWork(client *rpc.Client) {
fmt.Println("watch:", keyChanged)
} ()
err := client.Call("KVStoreService.Set", [2]string{"abc", "abc-value"}, new(struct{}))
err := client.Call(
"KVStoreService.Set", [2]string{"abc", "abc-value"},
new(struct{}),
)
if err != nil {
log.Fatal(err)
}

View File

@ -129,8 +129,12 @@ type HelloServiceServer interface {
Channel(HelloService_ChannelServer) error
}
type HelloServiceClient interface {
Hello(ctx context.Context, in *String, opts ...grpc.CallOption) (*String, error)
Channel(ctx context.Context, opts ...grpc.CallOption) (HelloService_ChannelClient, error)
Hello(ctx context.Context, in *String, opts ...grpc.CallOption) (
*String, error,
)
Channel(ctx context.Context, opts ...grpc.CallOption) (
HelloService_ChannelClient, error,
)
}
```
@ -356,11 +360,15 @@ func main() {
client := NewPubsubServiceClient(conn)
_, err = client.Publish(context.Background(), &String{Value: "golang: hello Go"})
_, err = client.Publish(
context.Background(), &String{Value: "golang: hello Go"},
)
if err != nil {
log.Fatal(err)
}
_, err = client.Publish(context.Background(), &String{Value: "docker: hello Docker"})
_, err = client.Publish(
context.Background(), &String{Value: "docker: hello Docker"},
)
if err != nil {
log.Fatal(err)
}
@ -378,7 +386,9 @@ func main() {
defer conn.Close()
client := NewPubsubServiceClient(conn)
stream, err := client.SubscribeTopic(context.Background(), &String{Value: "golang:"})
stream, err := client.SubscribeTopic(
context.Background(), &String{Value: "golang:"},
)
if err != nil {
log.Fatal(err)
}

View File

@ -116,7 +116,9 @@ func main() {
RootCAs: certPool,
})
conn, err := grpc.Dial("localhost:5000", grpc.WithTransportCredentials(creds))
conn, err := grpc.Dial(
"localhost:5000", grpc.WithTransportCredentials(creds),
)
if err != nil {
log.Fatal(err)
}
@ -210,7 +212,9 @@ type Authentication struct {
Password string
}
func (a *Authentication) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {
func (a *Authentication) GetRequestMetadata(context.Context, ...string) (
map[string]string, error,
) {
return map[string]string{"user":a.User, "password": a.Password}, nil
}
func (a *Authentication) RequireTransportSecurity() bool {
@ -396,7 +400,9 @@ func main() {
mux.ServeHTTP(w, r)
return
}
if strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
if strings.Contains(
r.Header.Get("Content-Type"), "application/grpc",
) {
grpcServer.ServeHTTP(w, r) // gRPC Server
return
}

View File

@ -40,7 +40,8 @@ grpcurl中最常使用的是list命令用于获取服务或服务方法的列
```shell
$ grpcurl localhost:1234 list
Failed to dial target host "localhost:1234": tls: first record does not look like a TLS handshake
Failed to dial target host "localhost:1234": tls: first record does not \
look like a TLS handshake
```
如果grpc服务正常但是服务没有启动reflection反射服务将会遇到以下错误