首页 > 其他分享 >Go RPC 库

Go RPC 库

时间:2024-02-02 22:34:07浏览次数:27  
标签:string err fmt args RPC kv Go reply

RPC(Remote Poresedure Call)是远程方法调用的缩写。Go的RPC库可以实现通过网络或者其他I/O方式远程调用对象的方法。

服务器注册一个对象,让它作为一个以对象类型命名的服务,让这个对象导出的方法可以被远程调用。一个服务器可以注册多个不同类型的对象,但是不能注册同一类型的多个对象。

一个能够被远程调用的方法应该像下面这样:

func (t *T) MethodName(argType T1, replyType *T2) error

一个简单的例子:实现简单的kv存储,并(在同一台机器上)通过RPC调用Put和Get方法。

package main

import (
	"fmt"
	"log"
	"net"
	"net/http"
	"net/rpc"
	"sync"
	"time"
)

// RPC struct definition

type PutArgs struct {
	Key string
	Val string
}

type PutReply struct {
	Ok bool
}

type GetArgs struct {
	Key string
}

type GetReply struct {
	Val string
}

type Kv struct {
	data map[string]string
	mu   sync.Mutex
}

// server

func (kv *Kv) Get(args *GetArgs, reply *GetReply) error {
	kv.mu.Lock()
	defer kv.mu.Unlock()
	reply.Val = kv.data[args.Key]
	return nil
}

func (kv *Kv) Put(args *PutArgs, reply *PutReply) error {
	kv.mu.Lock()
	defer kv.mu.Unlock()
	kv.data[args.Key] = args.Val
	reply.Ok = true
	return nil
}

func KvServer() {
	kv := new(Kv)
	kv.data = make(map[string]string)
	rpc.Register(kv)
	rpc.HandleHTTP()
	l, err := net.Listen("tcp", ":1234")
	if err != nil {
		log.Fatal("listen error: ", err)
	}
	http.Serve(l, nil)
}

// client interface

func get(key string) string {
	client, err := rpc.DialHTTP("tcp", "127.0.0.1"+":1234")
	if err != nil {
		log.Fatal("dialing:", err)
	}
	args := GetArgs{key}
	reply := GetReply{}
	e := client.Call("Kv.Get", args, &reply)
	if e != nil {
		log.Fatal("get error", e)
	}
	client.Close()
	return reply.Val
}

func put(key string, val string) bool {
	client, err := rpc.DialHTTP("tcp", "127.0.0.1"+":1234")
	if err != nil {
		log.Fatal("dialing:", err)
	}
	args := PutArgs{key, val}
	reply := PutReply{}
	e := client.Call("Kv.Put", args, &reply)
	if e != nil {
		log.Fatal("put error", e)
	}
	client.Close()
	return reply.Ok
}

// test

func main() {
	go KvServer()
	time.Sleep(time.Second) // wait for server to start
	fmt.Println(put("key1", "value1"))
	fmt.Println(put("key2", "value2"))
	fmt.Println(put("key3", "value3"))
	fmt.Println(get("key1"))
	fmt.Println(get("key2"))
	fmt.Println(get("key3"))
	fmt.Println(get("value1"))
}

标签:string,err,fmt,args,RPC,kv,Go,reply
From: https://www.cnblogs.com/tea-in-the-snow/p/18004123

相关文章

  • 数学概率拆分——cf_921_D.Good Trip
    目录问题概述思路想法参考代码问题反思问题概述原题参考:D.GoodTrip大致意思就是一个老师带着n个孩子,其中有m对是朋友,每对朋友之间有一个友谊值,不是朋友的则是0,这个老师要出去玩k次,每次可以带上两个小朋友(为什么不能一起带,这是偏爱!!!),如果这两个小朋友是朋友关系的话,那么他们的......
  • Golang 向已关闭的chan读写数据会怎样
    1.向已关闭的chan写会直接panic,报sendtoclosechannel错误packagemainfuncmain(){ //创建缓冲区为4的字符串chan schoolChan:=make(chanstring,4) //放入3个值 schoolChan<-"国防科大" schoolChan<-"北京大学" schoolChan<-"湖南大学" //......
  • Golang中make和new的区别
    1.相同点都是内建函数,都是在堆上分配内存,都需要传递类型参数2.不同点传递的参数不一样,new函数只接收一个参数,make函数可以接收一个以上的参数packagemainimport"fmt"funcmain(){ //int类型0值的指针,返回的值是以0x开头的16进制整数,参数个数为1 intZeroValueP......
  • P9309 [EGOI2021] Number of Zeros题解
    模拟赛时以为是进位制的题目,结果还做出来了。此题解解法与其它相似,但观察的角度不同(作者的脑回路不同)。此题问\(a\simb\)的最小公倍数中后导\(0\)的个数,即求其中\(2\)和\(5\)个数的最小值。分别计算即可,想到进位制,以\(a=10\),\(b=12\)时\(2\)的个数为例:1001(9)......
  • 在ubuntu16.04下,源码编译安装特定版本的MongoDB PHP扩展
    背景:我的php项目在连接其他mongo库时报:Serveratxxx:27017reportswireversion5,butthisversionoflibmongocrequiresatleast6(MongoDB3.6)原因:本地MongoDBPHP扩展的版本过高解决方法:降低本地PHP扩展MongoDB版本,现在要降到mongodb-1.12.0版本步骤:1:下载......
  • 千万级高性能长连接Go服务架构实践
    作者|glstr导读移动互联网时代,长连接服务成为了提升应用实时性和互动性的基础服务。本文主要介绍了百度系内基于golang实现的统一长连接服务。主要从统一长连接功能实现和性能优化等角度,描述了统一长连接服务在设计、开发和维护过程中面临的问题和挑战,重点介绍了解决相关问题和挑......
  • 第六十三天 cookie, session与Django中间件
    一、cookie与session简介"""HTTP协议四大特性1.基于请求响应2.基于TCP、IP作用于应用层之上协议 3.无状态服务端无法识别客户端的状态 1.互联网刚开始兴起的的时候所有人访问网址都是一样的数据 服务端无法识别客户端问题不大 2.互联网发展淘宝、京东、阿里 服务端......
  • 桌面应用开发GOTK3 Glade (GO语言)
    目录Github简介环境变量官方示例demo.gladeGithubmain.goGithubhttps://github.com/GNOME/gtkhttps://github.com/gotk3/gotk3gitclonehttps://github.com/gotk3/gotk3.git简介gotk3项目为GTK3和依赖项目提供Go绑定。每个组件都有自己的子目录,用作包的导入路径......
  • CF921 D. Good Trip
    题面代码点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineIOSios::sync_with_stdio(0);cin.tie(0);cout.tie(0);#definerep(i,a,n)for(inti=a;i<=n;i++)#defineper(i,a,n)for(inti=n;i>=a;i--)#definefirstfi#defineseconfse#defi......
  • Go语言精进之路读书笔记第12条——使用复合字面值作为初值构造器
    有些时候,零值并非最好的选择,我们有必要为变量赋予适当的初值以保证其后续以正确的状态参与业务流程计算,尤其是Go语言中的一些复合类型的变量。Go提供了复合字面值(compositeliteral)语法可以作为复合类型变量的初值构造器。Go语言中的复合类型包括结构体、数组/切片和map。Go提供......