From be43d55cc11545338dd01ee9b6a33a8740ca693b Mon Sep 17 00:00:00 2001 From: vCaesar Date: Sat, 10 Jun 2017 12:16:14 +0800 Subject: [PATCH] Format and remove 08.4.md spaces --- zh/08.4.md | 522 ++++++++++++++++++++++++++--------------------------- 1 file changed, 261 insertions(+), 261 deletions(-) diff --git a/zh/08.4.md b/zh/08.4.md index 086c2258..3da58db5 100644 --- a/zh/08.4.md +++ b/zh/08.4.md @@ -47,50 +47,50 @@ http的服务端代码实现如下: ```Go - package main +package main - import ( - "errors" - "fmt" - "net/http" - "net/rpc" - ) +import ( + "errors" + "fmt" + "net/http" + "net/rpc" +) - type Args struct { - A, B int +type Args struct { + A, B int +} + +type Quotient struct { + Quo, Rem int +} + +type Arith int + +func (t *Arith) Multiply(args *Args, reply *int) error { + *reply = args.A * args.B + return nil +} + +func (t *Arith) Divide(args *Args, quo *Quotient) error { + if args.B == 0 { + return errors.New("divide by zero") } + quo.Quo = args.A / args.B + quo.Rem = args.A % args.B + return nil +} - type Quotient struct { - Quo, Rem int - } - - type Arith int - - func (t *Arith) Multiply(args *Args, reply *int) error { - *reply = args.A * args.B - return nil - } - - func (t *Arith) Divide(args *Args, quo *Quotient) error { - if args.B == 0 { - return errors.New("divide by zero") - } - quo.Quo = args.A / args.B - quo.Rem = args.A % args.B - return nil - } - - func main() { - - arith := new(Arith) - rpc.Register(arith) - rpc.HandleHTTP() - - err := http.ListenAndServe(":1234", nil) - if err != nil { - fmt.Println(err.Error()) - } +func main() { + + arith := new(Arith) + rpc.Register(arith) + rpc.HandleHTTP() + + err := http.ListenAndServe(":1234", nil) + if err != nil { + fmt.Println(err.Error()) } +} ``` 通过上面的例子可以看到,我们注册了一个Arith的RPC服务,然后通过`rpc.HandleHTTP`函数把该服务注册到了HTTP协议上,然后我们就可以利用http的方式来传递数据了。 @@ -99,59 +99,59 @@ http的服务端代码实现如下: ```Go - package main +package main - import ( - "fmt" - "log" - "net/rpc" - "os" - ) +import ( + "fmt" + "log" + "net/rpc" + "os" +) - type Args struct { - A, B int +type Args struct { + A, B int +} + +type Quotient struct { + Quo, Rem int +} + +func main() { + if len(os.Args) != 2 { + fmt.Println("Usage: ", os.Args[0], "server") + os.Exit(1) } + serverAddress := os.Args[1] - type Quotient struct { - Quo, Rem int + client, err := rpc.DialHTTP("tcp", serverAddress+":1234") + if err != nil { + log.Fatal("dialing:", err) } - - func main() { - if len(os.Args) != 2 { - fmt.Println("Usage: ", os.Args[0], "server") - os.Exit(1) - } - serverAddress := os.Args[1] - - client, err := rpc.DialHTTP("tcp", serverAddress+":1234") - if err != nil { - log.Fatal("dialing:", err) - } - // Synchronous call - args := Args{17, 8} - var reply int - err = client.Call("Arith.Multiply", args, &reply) - if err != nil { - log.Fatal("arith error:", err) - } - fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply) - - var quot Quotient - err = client.Call("Arith.Divide", args, ") - if err != nil { - log.Fatal("arith error:", err) - } - fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem) - + // Synchronous call + args := Args{17, 8} + var reply int + err = client.Call("Arith.Multiply", args, &reply) + if err != nil { + log.Fatal("arith error:", err) } + fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply) + + var quot Quotient + err = client.Call("Arith.Divide", args, ") + if err != nil { + log.Fatal("arith error:", err) + } + fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem) + +} ``` 我们把上面的服务端和客户端的代码分别编译,然后先把服务端开启,然后开启客户端,输入代码,就会输出如下信息: ```Go - $ ./http_c localhost - Arith: 17*8=136 - Arith: 17/8=2 remainder 1 +$ ./http_c localhost +Arith: 17*8=136 +Arith: 17/8=2 remainder 1 ``` 通过上面的调用可以看到参数和返回值是我们定义的struct类型,在服务端我们把它们当做调用函数的参数的类型,在客户端作为`client.Call`的第2,3两个参数的类型。客户端最重要的就是这个Call函数,它有3个参数,第1个要调用的函数的名字,第2个是要传递的参数,第3个要返回的参数(注意是指针类型),通过上面的代码例子我们可以发现,使用Go的RPC实现相当的简单,方便。 @@ -159,68 +159,68 @@ http的服务端代码实现如下: 上面我们实现了基于HTTP协议的RPC,接下来我们要实现基于TCP协议的RPC,服务端的实现代码如下所示: ```Go - package main +package main - import ( - "errors" - "fmt" - "net" - "net/rpc" - "os" - ) +import ( + "errors" + "fmt" + "net" + "net/rpc" + "os" +) - type Args struct { - A, B int +type Args struct { + A, B int +} + +type Quotient struct { + Quo, Rem int +} + +type Arith int + +func (t *Arith) Multiply(args *Args, reply *int) error { + *reply = args.A * args.B + return nil +} + +func (t *Arith) Divide(args *Args, quo *Quotient) error { + if args.B == 0 { + return errors.New("divide by zero") } + quo.Quo = args.A / args.B + quo.Rem = args.A % args.B + return nil +} - type Quotient struct { - Quo, Rem int - } +func main() { - type Arith int + arith := new(Arith) + rpc.Register(arith) - func (t *Arith) Multiply(args *Args, reply *int) error { - *reply = args.A * args.B - return nil - } + tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234") + checkError(err) - func (t *Arith) Divide(args *Args, quo *Quotient) error { - if args.B == 0 { - return errors.New("divide by zero") - } - quo.Quo = args.A / args.B - quo.Rem = args.A % args.B - return nil - } + listener, err := net.ListenTCP("tcp", tcpAddr) + checkError(err) - func main() { - - arith := new(Arith) - rpc.Register(arith) - - tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234") - checkError(err) - - listener, err := net.ListenTCP("tcp", tcpAddr) - checkError(err) - - for { - conn, err := listener.Accept() - if err != nil { - continue - } - rpc.ServeConn(conn) - } - - } - - func checkError(err error) { + for { + conn, err := listener.Accept() if err != nil { - fmt.Println("Fatal error ", err.Error()) - os.Exit(1) + continue } + rpc.ServeConn(conn) } +} + +func checkError(err error) { + if err != nil { + fmt.Println("Fatal error ", err.Error()) + os.Exit(1) + } +} + ``` 上面这个代码和http的服务器相比,不同在于:在此处我们采用了TCP协议,然后需要自己控制连接,当有客户端连接上来后,我们需要把这个连接交给rpc来处理。 @@ -229,51 +229,51 @@ http的服务端代码实现如下: ```Go - package main +package main - import ( - "fmt" - "log" - "net/rpc" - "os" - ) +import ( + "fmt" + "log" + "net/rpc" + "os" +) - type Args struct { - A, B int +type Args struct { + A, B int +} + +type Quotient struct { + Quo, Rem int +} + +func main() { + if len(os.Args) != 2 { + fmt.Println("Usage: ", os.Args[0], "server:port") + os.Exit(1) } + service := os.Args[1] - type Quotient struct { - Quo, Rem int + client, err := rpc.Dial("tcp", service) + if err != nil { + log.Fatal("dialing:", err) } - - func main() { - if len(os.Args) != 2 { - fmt.Println("Usage: ", os.Args[0], "server:port") - os.Exit(1) - } - service := os.Args[1] - - client, err := rpc.Dial("tcp", service) - if err != nil { - log.Fatal("dialing:", err) - } - // Synchronous call - args := Args{17, 8} - var reply int - err = client.Call("Arith.Multiply", args, &reply) - if err != nil { - log.Fatal("arith error:", err) - } - fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply) - - var quot Quotient - err = client.Call("Arith.Divide", args, ") - if err != nil { - log.Fatal("arith error:", err) - } - fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem) - + // Synchronous call + args := Args{17, 8} + var reply int + err = client.Call("Arith.Multiply", args, &reply) + if err != nil { + log.Fatal("arith error:", err) } + fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply) + + var quot Quotient + err = client.Call("Arith.Divide", args, ") + if err != nil { + log.Fatal("arith error:", err) + } + fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem) + +} ``` 这个客户端代码和http的客户端代码对比,唯一的区别一个是DialHTTP,一个是Dial(tcp),其他处理一模一样。 @@ -283,121 +283,121 @@ JSON RPC是数据编码采用了JSON,而不是gob编码,其他和上面介 ```Go - package main +package main - import ( - "errors" - "fmt" - "net" - "net/rpc" - "net/rpc/jsonrpc" - "os" - ) +import ( + "errors" + "fmt" + "net" + "net/rpc" + "net/rpc/jsonrpc" + "os" +) - type Args struct { - A, B int +type Args struct { + A, B int +} + +type Quotient struct { + Quo, Rem int +} + +type Arith int + +func (t *Arith) Multiply(args *Args, reply *int) error { + *reply = args.A * args.B + return nil +} + +func (t *Arith) Divide(args *Args, quo *Quotient) error { + if args.B == 0 { + return errors.New("divide by zero") } + quo.Quo = args.A / args.B + quo.Rem = args.A % args.B + return nil +} - type Quotient struct { - Quo, Rem int - } +func main() { - type Arith int + arith := new(Arith) + rpc.Register(arith) - func (t *Arith) Multiply(args *Args, reply *int) error { - *reply = args.A * args.B - return nil - } + tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234") + checkError(err) - func (t *Arith) Divide(args *Args, quo *Quotient) error { - if args.B == 0 { - return errors.New("divide by zero") - } - quo.Quo = args.A / args.B - quo.Rem = args.A % args.B - return nil - } + listener, err := net.ListenTCP("tcp", tcpAddr) + checkError(err) - func main() { - - arith := new(Arith) - rpc.Register(arith) - - tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234") - checkError(err) - - listener, err := net.ListenTCP("tcp", tcpAddr) - checkError(err) - - for { - conn, err := listener.Accept() - if err != nil { - continue - } - jsonrpc.ServeConn(conn) - } - - } - - func checkError(err error) { + for { + conn, err := listener.Accept() if err != nil { - fmt.Println("Fatal error ", err.Error()) - os.Exit(1) + continue } + jsonrpc.ServeConn(conn) } +} + +func checkError(err error) { + if err != nil { + fmt.Println("Fatal error ", err.Error()) + os.Exit(1) + } +} + ``` 通过示例我们可以看出 json-rpc是基于TCP协议实现的,目前它还不支持HTTP方式。 请看客户端的实现代码: ```Go - package main +package main - import ( - "fmt" - "log" - "net/rpc/jsonrpc" - "os" - ) +import ( + "fmt" + "log" + "net/rpc/jsonrpc" + "os" +) - type Args struct { - A, B int +type Args struct { + A, B int +} + +type Quotient struct { + Quo, Rem int +} + +func main() { + if len(os.Args) != 2 { + fmt.Println("Usage: ", os.Args[0], "server:port") + log.Fatal(1) } + service := os.Args[1] - type Quotient struct { - Quo, Rem int + client, err := jsonrpc.Dial("tcp", service) + if err != nil { + log.Fatal("dialing:", err) } - - func main() { - if len(os.Args) != 2 { - fmt.Println("Usage: ", os.Args[0], "server:port") - log.Fatal(1) - } - service := os.Args[1] - - client, err := jsonrpc.Dial("tcp", service) - if err != nil { - log.Fatal("dialing:", err) - } - // Synchronous call - args := Args{17, 8} - var reply int - err = client.Call("Arith.Multiply", args, &reply) - if err != nil { - log.Fatal("arith error:", err) - } - fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply) - - var quot Quotient - err = client.Call("Arith.Divide", args, ") - if err != nil { - log.Fatal("arith error:", err) - } - fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem) - + // Synchronous call + args := Args{17, 8} + var reply int + err = client.Call("Arith.Multiply", args, &reply) + if err != nil { + log.Fatal("arith error:", err) } - + fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply) + + var quot Quotient + err = client.Call("Arith.Divide", args, ") + if err != nil { + log.Fatal("arith error:", err) + } + fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem) + +} + ``` ## 总结 Go已经提供了对RPC的良好支持,通过上面HTTP、TCP、JSON RPC的实现,我们就可以很方便的开发很多分布式的Web应用,我想作为读者的你已经领会到这一点。但遗憾的是目前Go尚未提供对SOAP RPC的支持,欣慰的是现在已经有第三方的开源实现了。