mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
fmt code
This commit is contained in:
parent
8c25545f9d
commit
9ad62fe063
@ -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码,可以避免出现多字节的字符)。
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -422,7 +422,7 @@ func main {
|
||||
}
|
||||
}()
|
||||
|
||||
...
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
|
@ -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字符串:
|
||||
|
@ -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()),
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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反射服务,将会遇到以下错误:
|
||||
|
Loading…
x
Reference in New Issue
Block a user