前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go rpc示例

go rpc示例

作者头像
ccf19881030
发布2020-11-26 11:49:20
3940
发布2020-11-26 11:49:20
举报
文章被收录于专栏:ccf19881030的博客ccf19881030的博客

最近在Youtube上面看到一个关于:golang rpc包的示例视频:youtube视频地址:Building a Basic RPC Server and Client with Go,其相应源代码的Github仓库地址为:https://github.com/tensor-programming/go-basic-rpc,需要的话可以自行获取:

代码语言:javascript
复制
git clone https://github.com/tensor-programming/go-basic-rpc.git

golang rpc包

关于golang中的rpc库,可以查看官方文档:https://golang.org/pkg/net/rpc/https://pkg.go.dev/net/rpc,如下图所示:

golang rpc
golang rpc

简单的示例(不使用rpc)

下面对一个带有Title和Body的Item数组对象database,编写增删改查的方法,并进行简单的测试,相应的Go代码示例如下:

代码语言:javascript
复制
package main

import (
	"fmt"
)

type Item struct {
	Title string
	Body  string
}

var database []Item

// 根据title名称从database数组中获取对应的Item对象
func GetByName(title string) Item {
	var getItem Item

	for _, val := range database {
		if val.Title == title {
			getItem = val
		}
	}

	return getItem
}

// 添加一个新的Item对象
func AddItem(item Item) Item {
	database = append(database, item)
	return item
}

// 根据title在database中查询对应的Item对象,如果存在则进行更新
func EditItem(title string, edit Item) Item {
	var changed Item

	for idx, val := range database {
		if val.Title == title {
			database[idx] = edit
			changed = edit
		}
	}

	return changed
}

// 删除某个item对象
func DeleteItem(item Item) Item {
	var del Item

	for idx, val := range database {
		if val.Title == item.Title && val.Body == item.Body {
			database = append(database[:idx], database[idx+1:]...)
			del = val
			break
		}
	}

	return del
}

func main() {
	fmt.Println("initial database: ", database)
	a := Item{"first", "a test item"}
	b := Item{"second", "a second item"}
	c := Item{"third", "a third item"}

	AddItem(a)
	AddItem(b)
	AddItem(c)

	fmt.Println("second database: ", database)

	DeleteItem(b)
	fmt.Println("third database: ", database)

	EditItem("third", Item{"fourth", "a new item"})
	fmt.Println("fourth database: ", database)

	x := GetByName("fourth")
	y := GetByName("first")
	fmt.Println(x, y)
}

执行命令go run main,go得出如下的输出:

test main.go
test main.go

go_basic_rpc示例(包括rpc服务端和rpc客户端)

首先创建一个go-basic-rpc的目录,在其下创建一个server.go用于编写go rpc服务端,再创建一个client目录,然后在client目录下创建一个client.go文件用于编写go rpc客户端。最终的目录结构如下所示:

go_basic_rpc的目录结构
go_basic_rpc的目录结构

go rpc服务端server.go代码如下:

代码语言:javascript
复制
package main

import (
	"log"
	"net"
	"net/http"
	"net/rpc"
)

type Item struct {
	Title string
	Body  string
}

type API int

var database []Item

func (a *API) GetDB(empty string, reply *[]Item) error {
	*reply = database
	return nil
}

func (a *API) GetByName(title string, reply *Item) error {
	var getItem Item

	for _, val := range database {
		if val.Title == title {
			getItem = val
		}
	}

	*reply = getItem

	return nil
}

func (a *API) AddItem(item Item, reply *Item) error {
	database = append(database, item)
	*reply = item
	return nil
}

func (a *API) EditItem(item Item, reply *Item) error {
	var changed Item

	for idx, val := range database {
		if val.Title == item.Title {
			database[idx] = Item{item.Title, item.Body}
			changed = database[idx]
		}
	}

	*reply = changed
	return nil
}

func (a *API) DeleteItem(item Item, reply *Item) error {
	var del Item

	for idx, val := range database {
		if val.Title == item.Title && val.Body == item.Body {
			database = append(database[:idx], database[idx+1:]...)
			del = item
			break
		}
	}

	*reply = del
	return nil
}

func main() {
	api := new(API)
	err := rpc.Register(api)
	if err != nil {
		log.Fatal("error registering API", err)
	}

	rpc.HandleHTTP()

	listener, err := net.Listen("tcp", ":4040")

	if err != nil {
		log.Fatal("Listener error", err)
	}
	log.Printf("serving rpc on port %d", 4040)
	http.Serve(listener, nil)

	if err != nil {
		log.Fatal("error serving: ", err)
	}

	// fmt.Println("initial database: ", database)
	// a := Item{"first", "a test item"}
	// b := Item{"second", "a second item"}
	// c := Item{"third", "a third item"}

	// AddItem(a)
	// AddItem(b)
	// AddItem(c)
	// fmt.Println("second database: ", database)

	// DeleteItem(b)
	// fmt.Println("third database: ", database)

	// EditItem("third", Item{"fourth", "a new item"})
	// fmt.Println("fourth database: ", database)

	// x := GetByName("fourth")
	// y := GetByName("first")
	// fmt.Println(x, y)

}

go rpc客户端client/client.go代码如下:

代码语言:javascript
复制
package main

import (
	"fmt"
	"log"
	"net/rpc"
)

type Item struct {
	Title string
	Body  string
}

func main() {
	var reply Item
	var db []Item

	client, err := rpc.DialHTTP("tcp", "localhost:4040")

	if err != nil {
		log.Fatal("Connection error: ", err)
	}

	a := Item{"First", "A first item"}
	b := Item{"Second", "A second item"}
	c := Item{"Third", "A third item"}

	client.Call("API.AddItem", a, &reply)
	client.Call("API.AddItem", b, &reply)
	client.Call("API.AddItem", c, &reply)
	client.Call("API.GetDB", "", &db)

	fmt.Println("Database: ", db)

	client.Call("API.EditItem", Item{"Second", "A new second item"}, &reply)

	client.Call("API.DeleteItem", c, &reply)
	client.Call("API.GetDB", "", &db)
	fmt.Println("Database: ", db)

	client.Call("API.GetByName", "First", &reply)
	fmt.Println("first item: ", reply)

}

运行rpc服务端和客户端

  • 运行rpc服务端
代码语言:javascript
复制
cd /root/Programming/GoPro/go-basic-rpc
go run server.go
  • 运行rpc客户端
代码语言:javascript
复制
cd /root/Programming/GoPro/go-basic-rpc/client
go run client.go
运行go_basic_rpc服务端和客户端
运行go_basic_rpc服务端和客户端

参考资料

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • golang rpc包
  • 简单的示例(不使用rpc)
  • go_basic_rpc示例(包括rpc服务端和rpc客户端)
    • go rpc服务端server.go代码如下:
      • go rpc客户端client/client.go代码如下:
        • 运行rpc服务端和客户端
        • 参考资料
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档