Go net/rpc 包总结

本文介绍了RPC(远程过程调用)的基本概念及其在Go语言中的实现方式。详细讲解了客户端和服务端的主要交互流程,包括连接建立、方法调用及响应处理等关键步骤,并给出了一个完整的示例程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RPC

rpc远程过程调用,go net/rpc包提供了通过网络访问一个对象的方法的能力。服务器需要注册对象, 通过对象的类型名暴露这个服务。注册后这个对象的输出方法就可以远程调用,这个库封装了底层传输的细节,包括序列化。服务器可以注册多个不同类型的对象,但是注册相同类型的多个对象的时候回出错。
通过阅读net/rpc包你可以学到互斥锁、goroutine、map、channel、interface、反射等相关知识。

Clinet.go

阅读源码我们可以得知连接分为
DialHTTP —— 连接到指定的网络地址http RPC服务器,监听默认的HTTP RPC路径
DialHTTPPath —— 连接在指定的网络地址和路径HTTP RPC服务器
NewClient —— 返回一个新的客户端句柄,在链接的有效期内链接服务端发送请求
NewClientWithCodec——与NewClient相似,但是它使用指定得编码器编码请求,解码返回
我们可以看出DialHTTP与DialHTTPPath可以归为一组,NewClient与NewClientWithCodec可以归为一组。
DialHTTP 和 DialHTTPPath 是通过HTTP的方式和服务器建立连接,他俩的区别之在于是否设置上下文路径。
NewClient使用默认编码NewClientWithCodec使用其它编码。
Clinet端比较重要的input方法。
从代码中我们可以看出其在一个for循环中首先读取了头,然后从map中获取值若为nil则调用了ReadResponseBody方法并传入了nil迫使放弃读取。这也印证了代码中所说的ReadResponseHeader与ReadResponseBody为成对调用的。
另一个为异步调用的Go异步调用函数。它返回call结构体。done的通道将在调用完成时发出相同的调用对象来发出信号。如果done为nil,Go将会分配一个新的channel。如果non-nil,done必须有缓存否则会崩溃。
故Client端在使用时有如下注意事项:
1. channel必须为有缓存的
2. ReadResponseHeader与ReadResponseBody配合使用
3. 客户端在一个链接结束后调用Close关闭
4. 若ReadResponseHeader失败则需要调用ReadResponseBody并传入nil迫使放弃。

Server.go

在服务端注册并发布方法需要满足一下条件:

  1. 导出的方法和导出的类型
  2. 两个参数都是导出的类型
  3. 第二个参数必须为指针
  4. 返回值为一个错误类型

注册方法:

Register与RegisterName,RegisterName与Register类似,但是使用传入的名字作为类型,代替接收者的具体类型。

监听

Accept—Accept接收监听的连接。并为每一个进入的连接提供请求
HandleHTTP—HandleHTTP再RPCPath注册一个HTTP handler作为RPC的消息。它必须调用http.Serve(),再go语句中调用
ServeCodec—运行这个server在一个单独连接
ServeConn—为连接提供服务直到客户端挂起,调用者使用go ServeConn调用。 ServeConn在连接中使用gob包进行写格式化
ServeHTTP—ServeHTTP执行http.Handler应答RPC请求
ServeRequest—就像是ServeCodec但是同步服务的请求。它在完成后不关闭编解码器

简单的示例

clinet.go

package main

import (
    "net/rpc"
    "fmt"
)

const (
    PORT = "127.0.0.1:10012"
    PROXY = "tcp"
)

type Hello struct {
    StrHello string
}

type ResStr struct {
    StrHi string
}

func main() {
    client, err := rpc.DialHTTP(PROXY, PORT)
    if err != nil {
        fmt.Println("dialing:", err)
    }

    var args = Hello{" Test rpc",}
    var reply string
    err = client.Call("Say.SayHello", args, &reply)
    if err != nil {
         fmt.Println("arith error:", err)
    }
    fmt.Println(reply)
    args = Hello{" Go invokes the function asynchronously",}
    res := new(ResStr)
    resCall  := client.Go("Say.SayHi",args,&res,nil) //异步调用
    replyCall := <-resCall.Done
    if replyCall.Error != nil {
        fmt.Println("arith error:", replyCall.Error)
    }
    fmt.Println(res.StrHi)
}

server.go

package main

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

const (
    SAY = "Hello"
    PORT = ":10012"
    PROXY = "tcp"
)

type Hello struct {
    StrHello string
}

type ResStr struct {
    StrHi string
}

type Say int

func (this *Say) SayHello(args *Hello, reply *string) error {
    *reply = SAY + args.StrHello
    return nil
}

func (this *Say) SayHi(args *Hello, reply *ResStr) error {
    reply.StrHi = SAY + args.StrHello
    return nil
}

func main() {
    hi := new(Say)
    rpc.Register(hi)
    rpc.HandleHTTP()
    l, e := net.Listen(PROXY,PORT)
    if e != nil {
        fmt.Println("listen error:", e)
    }
    http.Serve(l, nil)

}
<think>好的,用户遇到了Go模块中标准库缺失的问题,需要解决。首先,我需要理清可能的原因和对应的解决方案。根据用户提到的错误信息,可能涉及标准库如delve、liner、go.starlark.net、blackfriday、telemetry等,这些可能并非Go官方标准库的一部分,而是第三方。用户可能误解了这些属于标准库,或者在GOPATH下找不到它们,导致构建失败。 首先,标准库通常不需要手动安装,它们随Go安装一起提供。如果出现缺失,可能是Go环境安装不完整或版本不匹配。需要检查Go版本,使用go version确认,并考虑重新安装或升级。另外,GOPATH和GOMODULE的配置可能有问题。Go Modules启用后,依赖管理不再依赖GOPATH,但若项目未正确初始化模块,可能导致问题。用户需要确认是否在项目目录下执行了go mod init,并确保go.mod文件存在。 其次,提到的如delve(调试工具)、blackfriday(Markdown处理器)、go.starlark.net(嵌入Starlark语言)等,都是第三方库。用户可能没有正确获取这些依赖。需要使用go get命令安装,例如go get github.com/russross/blackfriday/v2。同时,检查go.mod和go.sum是否含这些依赖,必要时手动添加并运行go mod tidy。 另外,GOPATH的环境变量设置可能被覆盖或错误,需要检查GOPATH是否指向正确目录,并确认这些第三方是否被下载到GOPATH下的pkg/mod中。若使用Go Modules,GOPATH的角色已经弱化,主要依赖项目内的go.mod管理。 还有可能涉及特定工具的配置问题,例如Delve调试器需要确保其版本与Go版本兼容,或者重新安装Delve(go install github.com/go-delve/delve/cmd/dlv@latest)。对于telemetry相关的错误,可能与Go 1.15+的遥测功能有关,但通常不影响构建,除非有特定环境限制,可以尝试禁用遥测(GOTELEMETRY=off)。 总结解决方案步骤:1. 确认Go环境正确安装;2. 初始化Go模块;3. 使用go get安装缺失的第三方;4. 检查并更新依赖;5. 处理工具链问题;6. 环境变量检查。同时,用户可能需要区分标准库和第三方,正确管理依赖。</think>### 逐步解决方案:Go模块中标准库缺失问题 #### 1. **确认的真实性质** - **标准库**:Go的标准库(如`fmt`、`net/http`)无需手动安装,随Go环境自动提供。若提示缺失,可能是环境配置问题。 - **第三方**:例如: - `delve`:调试工具([github.com/go-delve/delve](https://github.com/go-delve/delve)) - `blackfriday`:Markdown处理器([github.com/russross/blackfriday](https://github.com/russross/blackfriday)) - `go.starlark.net`:Starlark语言嵌入库([go.starlark.net](https://github.com/google/starlark-go)) 若误将第三方当作标准库,需通过`go get`安装: ```bash go get github.com/russross/blackfriday/v2 go get go.starlark.net/@latest ``` #### 2. **检查Go环境配置** - **确认Go版本**: ```bash go version # 需≥1.11(支持Go Modules) ``` - **重新安装Go环境**: 若标准库缺失(如`fmt`报错),重新安装Go并检查环境变量`GOROOT`和`GOPATH`[^3]。 #### 3. **初始化Go模块** - 在项目根目录执行: ```bash go mod init <module-name> # 初始化模块 go mod tidy # 自动添加/移除依赖 ``` - 手动添加缺失到`go.mod`: ```go require ( github.com/go-delve/delve v1.20.1 go.starlark.net v0.0.0-20230831151026-0... ) ``` #### 4. **解决特定问题** - **Delve调试工具**: ```bash go install github.com/go-delve/delve/cmd/dlv@latest ``` - **Telemetry错误**: 禁用遥测(临时): ```bash export GOTELEMETRY=off ``` #### 5. **检查GOPATH与模块兼容性** - Go Modules启用后,依赖默认存储在`$GOPATH/pkg/mod`,无需手动操作。 - 确认环境变量: ```bash go env GOPATH # 查看当前GOPATH go env GOMOD # 确认当前模块路径 ``` #### 6. **更新依赖版本** - 强制更新所有依赖: ```bash go get -u ./... ``` --- ### 关键命令总结 | 问题类型 | 命令示例 | |--------------------|--------------------------------------------------------------------------| | 安装第三方 | `go get github.com/russross/blackfriday/v2` | | 初始化模块 | `go mod init example.com/project` | | 清理无效依赖 | `go mod tidy` | | 更新所有依赖 | `go get -u ./...` | | 重新安装Delve | `go install github.com/go-delve/delve/cmd/dlv@latest` | --- ### 相关问题 1. **如何区分Go标准库和第三方?** > 标准库列表见[官方文档](https://pkg.go.dev/std),未列出的均为第三方。 2. **Go Modules与GOPATH的关系是什么?** > Modules启用后,依赖优先从`go.mod`管理,存储于`$GOPATH/pkg/mod`,不再依赖`GOPATH/src`。 3. **如何修复`missing go.sum entry`错误?** > 运行`go mod tidy`或`go mod verify`同步依赖校验。 4. **Go 1.16+的默认模块行为有何变化?** > `go install`默认安装到`GOBIN`,且需显式指定`@version`(如`@latest`)。 --- ### 引用标注 [^1]: 关于Git库和中间件的引用,见Webhooks工具库说明。 [^2]: 视频处理库如FFmpeg绑定,参考相关Go文档。 : Go Modules的官方定义和操作指南,详见Go官方博客。 [^4]: DevOps工具链的集成方法,参考Go生态工具分类。 [^5]: Go到其他语言的编译工具,如GopherJS,需注意版本兼容性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值