首先,說一下目錄結構:

一、HttpRPC
1、建立服務文件
/*Go RPC的函數只有符合下面的條件才能被遠程訪問,不然會被忽略,詳細的要求如下:
函數必須是導出的(首字母大寫)
必須有兩個導出類型的參數,
第一個參數是接收的參數,第二個參數是返回給客戶端的參數,第二個參數必須是指針類型的
函數還要有一個返回值error
舉個例子,正確的RPC函數格式如下:
func (t *T) MethodName(argType T1, replyType *T2) error
*/
package common
import (
"errors"
)
type Args struct {
A, B float32
}
type Result struct {
Value float32
}
type MathService struct {
}
func (s *MathService) Add(args *Args, result *Result) error {
result.Value = args.A + args.B
return nil
}
func (s *MathService) Divide(args *Args, result *Result) error {
if args.B == 0 {
return errors.New("除數不能為零!")
}
result.Value = args.A / args.B
return nil
}
2、服務端代碼:
package main
import (
"fmt"
"net/http"
"net/rpc"
"../common"
)
func main() {
var ms = new(common.MathService)
rpc.Register(ms)
rpc.HandleHTTP() //將Rpc綁定到HTTP協議上。
fmt.Println("啟動服務...")
err := http.ListenAndServe(":1234", nil)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println("服務已停止!")
}
3、客戶端調用代碼:
package main
import (
"fmt"
"net/rpc"
"../common"
)
func main() {
var args = common.Args{17, 8}
var result = common.Result{}
var client, err = rpc.DialHTTP("tcp", "127.0.0.1:1234")
if err != nil {
fmt.Println("連接RPC服務失敗:", err)
}
err = client.Call("MathService.Divide", args, &result)
if err != nil {
fmt.Println("調用失敗:", err)
}
fmt.Println("調用結果:", result.Value)
}
4、測試:

二、HttpRPC
1、建立服務文件
/*Go RPC的函數只有符合下面的條件才能被遠程訪問,不然會被忽略,詳細的要求如下:
函數必須是導出的(首字母大寫)
必須有兩個導出類型的參數,
第一個參數是接收的參數,第二個參數是返回給客戶端的參數,第二個參數必須是指針類型的
函數還要有一個返回值error
舉個例子,正確的RPC函數格式如下:
func (t *T) MethodName(argType T1, replyType *T2) error
*/
package common
import (
"errors"
)
type Args struct {
A, B float32
}
type Result struct {
Value float32
}
type MathService struct {
}
func (s *MathService) Add(args *Args, result *Result) error {
result.Value = args.A + args.B
return nil
}
func (s *MathService) Divide(args *Args, result *Result) error {
if args.B == 0 {
return errors.New("除數不能為零!")
}
result.Value = args.A / args.B
return nil
}
2、服務端文件
package main
import (
"fmt"
"net"
"net/rpc"
"../common"
)
func main() {
var ms = new(common.MathService) //實例化服務對像
rpc.Register(ms) //注冊這個服務
fmt.Println("啟動服務...")
var address, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:1234") //定義TCP的服務承載地址
listener, err := net.ListenTCP("tcp", address) //監聽TCP連接
if err != nil {
fmt.Println("啟動失敗!", err)
}
for {
conn, err := listener.Accept() //如果接受到連接
if err != nil {
continue
}
fmt.Println("接收到一個調用請求...")
rpc.ServeConn(conn) //讓此rpc綁定到該Tcp連接上。
}
//fmt.Println("服務已停止!")
}
3、客戶端代碼:
// main.go
package main
import (
"fmt"
"net/rpc"
"../common"
)
func main() {
var client, err = rpc.Dial("tcp", "127.0.0.1:1234")
if err != nil {
fmt.Println("連接不到服務器:", err)
}
var args = common.Args{40, 3}
var result = common.Result{}
fmt.Println("開始調用!")
err = client.Call("MathService.Add", args, &result)
if err != nil {
fmt.Println("調用失敗!", err)
}
fmt.Println("調用成功!結果:", result.Value)
}
4、效果:

