最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang遠(yuǎn)程調(diào)用框架RPC的具體使用

 更新時間:2022年12月14日 09:25:49   作者:夢想畫家  
Remote Procedure Call (RPC) 是一種使用TCP協(xié)議從另一個系統(tǒng)調(diào)用應(yīng)用程序功能執(zhí)行的方法。Go有原生支持RPC服務(wù)器實現(xiàn),本文通過簡單實例介紹RPC的實現(xiàn)過程

gRPC

gRPC遠(yuǎn)程過程調(diào)用框架是基于動作的模式,類似遠(yuǎn)程調(diào)用微服務(wù)。這使得gRPC成為一種圍繞Protobufs構(gòu)建的進(jìn)程間通信(IPC)協(xié)議,用于處理客戶端和服務(wù)器之間的消息傳遞。gRPC非常適合密集而高效的通信,因為它支持客戶端和服務(wù)器流。

與REST對比

REST是一種基于資源的協(xié)議,客戶端根據(jù)請求體告訴服務(wù)器需要創(chuàng)建、讀取、更新或刪除哪些資源。gRPC還可以通過protobuf來定義接口,從而可以有更加嚴(yán)格的接口約束條件。gRPC為什么比REST更快?

gRPC利用HTTP/2協(xié)議,提供多種方式提供性能:

  • 報頭壓縮和重用以減少消息大小
  • 在單個TCP連接上同時發(fā)送多個請求和接收多個響應(yīng)的多路復(fù)用
  • 持久TCP連接用于單個TCP連接上的多個連續(xù)請求和響應(yīng)
  • 二進(jìn)制格式支持,如協(xié)議緩沖區(qū)

需求說明

Go RPC服務(wù)器允許注冊任何Go類型及其方法,通過RPC協(xié)議公開這些方法,即可以從遠(yuǎn)程客戶端按名稱進(jìn)行調(diào)用。我們要實現(xiàn)的需求可以簡單描述為:

  • 用戶可以添加書籍的信息
  • 用戶添加書籍的閱讀進(jìn)度
  • 用戶查詢書籍的閱讀進(jìn)度

當(dāng)然我們還可以實現(xiàn)其他更復(fù)雜的功能,這里為了簡化,僅說明這幾個方法。下面首先定義Book類型:

// Book represents a book entry
type Book struct {
ISBN string
Title, Author string
Year, Pages int
}
// ReadingList keeps tracks of books and pages read
type ReadingList struct {
Books []Book
Progress []int
}

ReadingList 類內(nèi)部包括兩個slice,模擬數(shù)據(jù)庫存儲書籍及對應(yīng)進(jìn)度。下面定義助手方法:

func (r *ReadingList) bookIndex(isbn string) int {
	for i := range r.Books {
		if isbn == r.Books[i].ISBN {
			return i
		}
	}
	return -1
}

上面通過ISBN查詢書籍對應(yīng)索引號,現(xiàn)在繼續(xù)在ReadingList類型上定義幾個方法:

// AddBook checks if the book is not present and adds it
func (r *ReadingList) AddBook(b Book) error {
	if b.ISBN == "" {
		return ErrISBN
	}
	if r.bookIndex(b.ISBN) != -1 {
		return ErrDuplicate
	}
	r.Books = append(r.Books, b)
	r.Progress = append(r.Progress, 0)
	return nil
}
// GetProgress returns the progress of a book
func (r *ReadingList) GetProgress(isbn string) (int, error) {
	if isbn == "" {
		return -1, ErrISBN
	}
	i := r.bookIndex(isbn)
	if i == -1 {
		return -1, ErrMissing
	}
	return r.Progress[i], nil
}
// 設(shè)置進(jìn)度
func (r *ReadingList) SetProgress(isbn string, pages int) error {
	if isbn == "" {
		return ErrISBN
	}
	i := r.bookIndex(isbn)
	if i == -1 {
		return ErrMissing
	}
	if p := r.Books[i].Pages; pages > p {
		pages = p
	}
	r.Progress[i] = pages
	return nil
}

我們需求就是通過RPC協(xié)議公開這些方法,讓客戶端進(jìn)行遠(yuǎn)程調(diào)用。下面實現(xiàn)RPC服務(wù)器。

創(chuàng)建RPC服務(wù)器

上節(jié)已經(jīng)準(zhǔn)備好了公開的方法,創(chuàng)建RPC服務(wù)需要遵守一些規(guī)則:

  • 方法的類型和方法自身必須是公開的(大寫開頭)
  • 方法有兩個參數(shù),類型也是公開的
  • 第二個參數(shù)是指針類型
  • 方法返回一個error類型

語法如下:

 func (t *T) Method(in T1, out *T2) error

知道了方法規(guī)范,下面對上節(jié)的方法進(jìn)行包裝,首先我們定義幾個錯誤類型:

// List of errors
var (
    ErrISBN = fmt.Errorf("missing ISBN")
    ErrDuplicate = fmt.Errorf("duplicate book")
    ErrMissing = fmt.Errorf("missing book")
)

再定義一個助手方法:

// sets the success pointer value from error
func setSuccess(err error, b *bool) error {
	*b = err == nil
	return err
}

首先實現(xiàn)Addbook和GetProgress包裝方法:

func (r *ReadingService) AddBook(b Book, success *bool) error {
	return setSuccess(r.ReadingList.AddBook(b), success)
}
func (r *ReadingService) GetProgress(isbn string, pages *int) (err error) {
	*pages, err = r.ReadingList.GetProgress(isbn)
	return err
}

由于更新閱讀進(jìn)度需要傳入兩個參數(shù),但rpc方法不能傳入多個參數(shù),因此我們定義類型進(jìn)行參數(shù)封裝:

type Progress struct {
	ISBN  string
	Pages int
}
func (r *ReadingService) SetProgress(p Progress, success *bool) error {
	return setSuccess(r.ReadingList.SetProgress(p.ISBN, p.Pages), success)
}

準(zhǔn)備了包裝方法,下面定義RPC服務(wù)就很簡單了:

func main() {
	if err := rpc.Register(&book.ReadingService{}); err != nil {
		log.Fatalln(err)
	}
	rpc.HandleHTTP()
	l, err := net.Listen("tcp", ":8900")
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("Server Started")
	if err := http.Serve(l, nil); err != nil {
		log.Fatal(err)
	}
}

服務(wù)端實現(xiàn)完畢,下面實現(xiàn)客戶端?;A(chǔ)類型Book,Progress再客戶端也需要使用,因此可以獨立定義進(jìn)行共享。

// Book represents a book entry
type Book struct {
	ISBN          string
	Title, Author string
	Year, Pages   int
}
type Progress struct {
	ISBN  string
	Pages int
}

實現(xiàn)客戶端

首先定義測試數(shù)據(jù):

const hp = "H.P. Lovecraft"
var books = []Book{
	{ISBN: "1540335534", Author: hp, Title: "The Call of Cthulhu", Pages: 36},
	{ISBN: "1980722803", Author: hp, Title: "The Dunwich Horror ", Pages: 53},
	{ISBN: "197620299X", Author: hp, Title: "The Shadow Over Innsmouth", Pages: 40},
	{ISBN: "1540335536", Author: hp, Title: "The Case of Charles Dexter Ward", Pages: 176},
}

下面定義rpc客戶端:

	client, err := rpc.DialHTTP("tcp", ":8900")
	if err != nil {
		log.Fatalln(err)
	}
	defer client.Close()

連接服務(wù)端后,可以調(diào)用服務(wù)端方法,下面定義統(tǒng)一方法進(jìn)行調(diào)用:

func callClient(client *rpc.Client, method string, in, out interface{}) {
	var r interface{}
	if err := client.Call(method, in, out); err != nil {
		out = err
	}
	switch v := out.(type) {
	case error:
		r = v
	case *int:
		r = *v
	case *bool:
		r = *v
	}
	log.Printf("%s: [%+v] -> %+v", method, in, r)
}

最后是循環(huán)測試數(shù)據(jù),依此調(diào)用RPC方法:

	for i, book := range books {
		callClient(client, "ReadingService.AddBook", book, new(bool))

		callClient(client, "ReadingService.SetProgress", Progress{
			ISBN:  book.ISBN,
			Pages: 10 + i*i,
		}, new(bool))

		callClient(client, "ReadingService.GetProgress", book.ISBN, new(int))
	}
}

完整代碼如下:

package main
import (
	log "log"
	"net/rpc"
)
func main() {
	client, err := rpc.DialHTTP("tcp", ":8900")
	if err != nil {
		log.Fatalln(err)
	}
	defer client.Close()
	for i, book := range books {
		callClient(client, "ReadingService.AddBook", book, new(bool))
		callClient(client, "ReadingService.SetProgress", Progress{
			ISBN:  book.ISBN,
			Pages: 10 + i*i,
		}, new(bool))
		callClient(client, "ReadingService.GetProgress", book.ISBN, new(int))
	}
}
// Book represents a book entry
type Book struct {
	ISBN          string
	Title, Author string
	Year, Pages   int
}
type Progress struct {
	ISBN  string
	Pages int
}
const hp = "H.P. Lovecraft"
var books = []Book{
	{ISBN: "1540335534", Author: hp, Title: "The Call of Cthulhu", Pages: 36},
	{ISBN: "1980722803", Author: hp, Title: "The Dunwich Horror ", Pages: 53},
	{ISBN: "197620299X", Author: hp, Title: "The Shadow Over Innsmouth", Pages: 40},
	{ISBN: "1540335536", Author: hp, Title: "The Case of Charles Dexter Ward", Pages: 176},
}
func callClient(client *rpc.Client, method string, in, out interface{}) {
	var r interface{}
	if err := client.Call(method, in, out); err != nil {
		out = err
	}
	switch v := out.(type) {
	case error:
		r = v
	case *int:
		r = *v
	case *bool:
		r = *v
	}
	log.Printf("%s: [%+v] -> %+v", method, in, r)
}

到此這篇關(guān)于Golang遠(yuǎn)程調(diào)用框架RPC的具體使用的文章就介紹到這了,更多相關(guān)Go RPC內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • go編譯so庫讓python引用編譯后沒有.h文件的問題

    go編譯so庫讓python引用編譯后沒有.h文件的問題

    有時python需要引用go的一些開源庫,這時就需要go編譯成python可調(diào)用的庫,本文給大家介紹了go編譯so庫讓python引用,編譯后沒有.h文件的問題,需要的朋友可以參考下
    2024-02-02
  • 一文教你打造一個簡易的Golang日志庫

    一文教你打造一個簡易的Golang日志庫

    這篇文章主要為大家詳細(xì)介紹了如何使用不超過130行的代碼,通過一系列g(shù)olang的特性,來打造一個簡易的golang日志庫,感興趣的小伙伴可以了解一下
    2023-06-06
  • Go語言實現(xiàn)Viper配置管理筆記

    Go語言實現(xiàn)Viper配置管理筆記

    Viper 是一個功能強(qiáng)大、靈活易用的配置管理工具,本文主要介紹了Go語言實現(xiàn)Viper配置管理筆記,具有一定的參考價值,感興趣的可以了解一下
    2025-04-04
  • Go常用技能日志log包創(chuàng)建使用示例

    Go常用技能日志log包創(chuàng)建使用示例

    這篇文章主要為大家介紹了Go常用技能日志log包創(chuàng)建使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Golang測試func?TestXX(t?*testing.T)的使用詳解

    Golang測試func?TestXX(t?*testing.T)的使用詳解

    一般Golang中的測試代碼都以xxx_test.go的樣式,在命名測試函數(shù)的時候以Testxx開頭,下面給大家介紹Golang測試func?TestXX(t?*testing.T)的使用,感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • Go高級特性探究之recover捕獲panic詳解

    Go高級特性探究之recover捕獲panic詳解

    在Go語言中,當(dāng)程序出現(xiàn)panic(即運(yùn)行時錯誤)時,程序會立即停止當(dāng)前的執(zhí)行流程,而recover函數(shù)的作用就是捕獲這個panic,下面就來看看具體是怎么操作的吧
    2023-06-06
  • Go實現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)

    Go實現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)

    這篇文章主要介紹了Go實現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)
    2022-01-01
  • golang實現(xiàn)數(shù)組分割的示例代碼

    golang實現(xiàn)數(shù)組分割的示例代碼

    本文主要介紹了golang實現(xiàn)數(shù)組分割的示例代碼,要求把數(shù)組分割成多個正整數(shù)大小的數(shù)組,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Golang編程并發(fā)工具庫MapReduce使用實踐

    Golang編程并發(fā)工具庫MapReduce使用實踐

    這篇文章主要為大家介紹了Golang并發(fā)工具庫MapReduce的使用實踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-04-04
  • Golang使用sqlx操作sqlite3數(shù)據(jù)庫的完整指南

    Golang使用sqlx操作sqlite3數(shù)據(jù)庫的完整指南

    這篇文章主要為大家詳細(xì)介紹了Golang使用sqlx操作sqlite3數(shù)據(jù)庫的相關(guān)知識,本文會結(jié)合sqlx給出一些操作數(shù)據(jù)庫的示例,并將常見功能封裝了函數(shù)接口形式,希望對大家有所幫助
    2025-12-12

最新評論

辽阳市| 来凤县| 鄂托克前旗| 卢湾区| 鹤庆县| 尚义县| 龙泉市| 介休市| 科技| 伽师县| 渭南市| 廊坊市| 林芝县| 那坡县| 顺平县| 南漳县| 满洲里市| 石家庄市| 江山市| 惠来县| 商南县| 方正县| 远安县| 贡嘎县| 柏乡县| 翁牛特旗| 新蔡县| 乐山市| 德格县| 什邡市| 磐石市| 林甸县| 江津市| 十堰市| 隆尧县| 瑞丽市| 巨鹿县| 南川市| 沙田区| 水富县| 博爱县|