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