Go如何實(shí)現(xiàn)兩個(gè)程序遠(yuǎn)程調(diào)用
net/rpc 則是為了讓兩個(gè) Go 程序之間直接對話。
RPC 讓你在寫代碼時(shí),調(diào)用另一臺遠(yuǎn)程機(jī)器上的函數(shù),就像調(diào)用本地的函數(shù)一樣簡單。
Go 標(biāo)準(zhǔn)庫中的 net/rpc 目前處于凍結(jié)狀態(tài)(不再增加新功能)。在現(xiàn)代的實(shí)際工程中,大家通常會(huì)使用 gRPC 或 Kratos 等更強(qiáng)大的框架。
RPC 的核心規(guī)則
net/rpc 要求你的函數(shù)必須遵守特定的簽名格式,才能被遠(yuǎn)程調(diào)用。
- 方法所屬的類型必須是導(dǎo)出的(首字母大寫)。
- 方法本身必須是導(dǎo)出的(首字母大寫)。
- 方法必須有兩個(gè)參數(shù),且都必須是導(dǎo)出類型或內(nèi)置類型。
- 方法的第二個(gè)參數(shù)必須是指針(因?yàn)榉?wù)器要把結(jié)果寫回這個(gè)指針里)。
- 方法必須返回一個(gè) error 類型。
func (t *T) MethodName(args T1, reply *T2) error
常用 API
服務(wù)端 API
- rpc.Register(rcvr any): 將你的結(jié)構(gòu)體注冊為 RPC 服務(wù)。結(jié)構(gòu)體名默認(rèn)就是服務(wù)名。
- rpc.HandleHTTP(): 如果你想讓 RPC 走 HTTP 協(xié)議,調(diào)用這個(gè)注冊路由。
- rpc.Accept(lis net.Listener): 如果你想走純 TCP 協(xié)議,用這個(gè)接收連接。
客戶端 API
- rpc.Dial(network, address string): 連接遠(yuǎn)程 RPC 服務(wù)器(比如傳 "tcp", "localhost:1234")。
- rpc.DialHTTP(network, address string): 連接走 HTTP 協(xié)議的 RPC 服務(wù)器。
- client.Call(serviceMethod string, args any, reply any): 同步調(diào)用遠(yuǎn)程函數(shù)。程序會(huì)在這里等待結(jié)果返回。
實(shí)例:實(shí)現(xiàn)一個(gè)遠(yuǎn)程乘法計(jì)算器
提供方:
package main
import (
"fmt"
"net"
"net/rpc"
)
// 1. 定義傳入的參數(shù)結(jié)構(gòu)體
type Args struct {
A, B int
}
// 2. 定義服務(wù)結(jié)構(gòu)體
type MathService struct{}
// 3. 實(shí)現(xiàn)服務(wù)方法(嚴(yán)格遵守 5 條規(guī)則)
func (m *MathService) Multiply(args Args, reply *int) error {
*reply = args.A * args.B
fmt.Printf("服務(wù)端執(zhí)行:計(jì)算 %d * %d\n", args.A, args.B)
return nil
}
func main() {
// 實(shí)例化服務(wù)
math := new(MathService)
// 注冊 RPC 服務(wù),客戶端就可以通過 "MathService.Multiply" 來調(diào)用了
rpc.Register(math)
// 啟動(dòng) TCP 監(jiān)聽
listener, err := net.Listen("tcp", ":1234")
if err != nil {
panic(err)
}
fmt.Println("RPC 服務(wù)端已啟動(dòng),監(jiān)聽端口 1234...")
// 接收請求并處理
rpc.Accept(listener)
}
調(diào)用方:
package main
import (
"fmt"
"log"
"net/rpc"
)
// 客戶端 需要定義一樣的參數(shù)結(jié)構(gòu)體
type Args struct {
A, B int
}
func main() {
// 1. 撥號連接 RPC 服務(wù)器
client, err := rpc.Dial("tcp", "localhost:1234")
if err != nil {
log.Fatal("撥號失敗:", err)
}
defer client.Close()
// 2. 準(zhǔn)備參數(shù)和接收結(jié)果的變量
args := Args{A: 10, B: 20}
var reply int
// 3. 發(fā)起調(diào)用! 第一個(gè)參數(shù)是 "結(jié)構(gòu)體名.方法名"
err = client.Call("MathService.Multiply", args, &reply)
if err != nil {
log.Fatal("調(diào)用失敗:", err)
}
fmt.Printf("調(diào)用成功!結(jié)果是: %d\n", reply)
}
到此這篇關(guān)于Go如何實(shí)現(xiàn)兩個(gè)程序遠(yuǎn)程調(diào)用的文章就介紹到這了,更多相關(guān)Go 程序遠(yuǎn)程調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang優(yōu)化目錄遍歷的實(shí)現(xiàn)方法
對于go1.16的新變化,大家印象最深的可能是io包的大規(guī)模重構(gòu),但這個(gè)重構(gòu)實(shí)際上還引進(jìn)了一個(gè)優(yōu)化,這篇文章要說的就是這個(gè)優(yōu)化,所以本將給大家介紹golang是如何優(yōu)化目錄遍歷的,需要的朋友可以參考下2024-08-08
詳解Go語言中結(jié)構(gòu)體與JSON間的轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了Go語言中結(jié)構(gòu)體與JSON間的轉(zhuǎn)換,文中的示例代碼講解詳細(xì),對學(xué)習(xí)Go語言有一定的幫助,需要的可以參考一下2022-12-12
詳解go語言 make(chan int, 1) 和 make (chan int) 的區(qū)別
這篇文章主要介紹了go語言 make(chan int, 1) 和 make (chan int) 的區(qū)別,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
Golang實(shí)現(xiàn)對map的并發(fā)讀寫的方法示例
這篇文章主要介紹了Golang實(shí)現(xiàn)對map的并發(fā)讀寫的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03
Go語言strconv包實(shí)現(xiàn)字符串和數(shù)值類型的相互轉(zhuǎn)換
這篇文章主要介紹了Go語言strconv包實(shí)現(xiàn)字符串和數(shù)值類型的相互轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
golang Gorm與數(shù)據(jù)庫完整性約束詳解
Go prometheus metrics條目自動(dòng)回收與清理方法

