mrpc

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 29, 2026 License: MIT Imports: 13 Imported by: 0

README

mrpc - 极简 RPC

一个基于 TCP + 反射的极简 Go RPC 框架,使用 msgpack 序列化,专注于单向非流式调用。

特性

  • 零依赖运行时:仅依赖 msgpack 用于消息序列化
  • 反射驱动:通过 Register 自动发现满足 func(req T, reply *U) error 签名的方法
  • 单向非流式:每次连接处理一个请求→一个响应,简单可靠
  • 长连接复用:客户端在多次 Call 之间复用 TCP 连接
  • 分级缓冲池:TieredPool 减少 GC 压力(可选)
  • 内置健康检查:开箱即用的服务端心跳检测

安装

go get github.com/23jdd/mrpc

快速开始

1. 定义服务
type Calculator struct{}

type MultiplyReq struct {
    A int
    B int
}

type MultiplyReply struct {
    Product int
}

// 签名必须为 func(req T, reply *U) error
func (c *Calculator) Multiply(req MultiplyReq, reply *MultiplyReply) error {
    reply.Product = req.A * req.B
    return nil
}
2. 启动服务端
lis, _ := net.Listen("tcp", "127.0.0.1:8080")
server := mrpc.NewServer(lis)

// 注册服务(名字用于客户端路由)
server.Register("Calculator", &Calculator{})

// 启动(阻塞)
server.Run()
3. 客户端调用
client := mrpc.NewClient("127.0.0.1", 8080)
defer client.Close()

req := &MultiplyReq{A: 7, B: 8}
var reply MultiplyReply
err := client.Call("Calculator.Multiply", req, &reply)
// reply.Product == 56

API 参考

Server
func NewServer(lis net.Listener) *Server

创建 RPC 服务端。lis 必须非 nil。

func (s *Server) Register(name string, target any) error

注册一个 RPC 服务实现。

参数:

  • name: 服务名,客户端使用 "name.MethodName" 格式调用
  • target: 服务实现,必须是指向 struct 的指针(如 &Calculator{})

注册规则:

  • 自动扫描 target 的所有导出方法
  • 只注册满足 func(req T, reply *U) error 的方法
  • 同名服务重复注册会覆盖之前的方法
  • 返回 nil 表示成功,否则返回错误描述

边界条件:

输入 行为
target 为值类型(非指针) 返回错误 "target must be a pointer to struct"
target 为 *int 等非结构体指针 返回错误 "target must point to a struct"
name 为空字符串 合法,方法注册为 ".MethodName"(不推荐)
结构体无符合签名的方法 返回 nil(不报错),但不注册任何方法
func (s *Server) Run()

启动服务端主循环,阻塞直到 lis.Accept() 返回不可恢复错误。

func (s *Server) Call(method string, req, reply any) error

在服务端内部进行反射调用(供测试或内部路由使用)。

Client
func NewClient(address string, port int) *Client

创建一个 RPC 客户端。

参数:

  • address: 服务端地址,支持 "127.0.0.1"、"localhost"、"::1" 等
  • port: 服务端端口号
func (c *Client) Dial() error

建立到服务端的 TCP 连接。若已有连接则先关闭旧连接。

func (c *Client) Call(method string, argv any, reply any) error

执行一次单向非流式 RPC 调用。

流程:

  1. 若未连接则自动 Dial()
  2. Encode(argv) → 发送请求帧
  3. 接收响应帧 → Decode(reply)

参数:

  • method: "ServiceName.MethodName"
  • argv: 请求参数指针(msgpack 需要指针才能编码)
  • reply: 响应参数指针(结果解码到此),可为 nil(跳过解码)

返回值:

  • nil: 调用成功
  • ErrShutdown: 客户端已关闭
  • 其他错误:网络错误、编解码错误、服务端返回的错误

边界条件:

场景 行为
未调用 Dial 直接 Call 自动拨号
argv 为 nil msgpack 编码为 nil,解码端需处理
reply 为 nil 跳过响应解码
服务端返回 error Call 返回包含错误消息的 error
网络断开 返回网络错误,下次 Call 自动重连
并发调用 Call 不安全,需要外部加锁
调用已 Close 的客户端 返回 ErrShutdown
func (c *Client) Close() error

关闭连接并标记客户端为 shut down 状态。幂等,可多次调用。

健康检查
func RegisterHealth() *healthService

返回一个实现了 Health.Check 方法的服务实例,注册后客户端可调用:

server.Register("Health", mrpc.RegisterHealth())

// 客户端:
var reply mrpc.HealthReply
client.Call("Health.Check", &mrpc.HealthRequest{}, &reply)
// reply.Ok == true 表示服务正常
func NewHealthChecker(interval, timeout time.Duration) *HealthChecker
func (hc *HealthChecker) Start(client *Client, maxFailures int, onFailure func(error))
func (hc *HealthChecker) Stop()

周期性健康检查器。Start 在后台 goroutine 中定期调用 Health.Check,连续 maxFailures 次失败后调用 onFailure。

分级缓冲池(可选)
func NewTieredPool(capacities ...int) *TieredPool
func (tp *TieredPool) Get(size int) []byte
func (tp *TieredPool) Put(buf []byte)

按容量分桶的缓冲池,减少 GC 压力。当前未直接集成到 RPC 调用中(可手动使用)。

协议

Request 和 Response 的低级 API:

// 帧协议
func WriteFrame(w io.Writer, payload []byte) error
func ReadFrame(r io.Reader) ([]byte, error)

// 请求
func NewRequest(method string, seq uint64, argv []byte) *Request
func SendRequest(w io.Writer, req *Request) error
func ReceiveRequest(r io.Reader) (*Request, error)

// 响应
func NewResponse(seq uint64, reply []byte, err string) *Response
func SendResponse(w io.Writer, resp *Response) error
func ReceiveResponse(r io.Reader) (*Response, error)

帧格式:

[4 字节 BigEndian 总长度] [payload...]
  • 最大 payload:10MB (MaxPayloadSize)
  • 超限时返回 ErrMaxPayload
编解码器
type Codec interface {
    Encode(v any) ([]byte, error)
    Decode(data []byte, v any) error
}

func NewMsgCodec() *MsgCodec

默认使用 msgpack。可通过实现 Codec 接口替换为 JSON、Protobuf 等。

线程安全

组件 安全性
Server.Register 非线程安全,需在 Run() 前完成注册
Server.Run 每个连接独立 goroutine,并发安全
Server.Call 非线程安全,仅供单 goroutine 调用
Client.Call 非线程安全,同一连接上的并发调用需外部加锁
Client.Close 线程安全(可通过 sync.Once 包装)
TieredPool Get/Put 线程安全(通过 sync.Pool)

限制

  • 单向非流式:不支持服务端推送、流式传输
  • 短连接处理:服务端每个连接只处理一个请求后关闭
  • 无超时控制:Call 无内置超时(可通过 context 在外部控制)
  • 无 TLS:纯 TCP 通信,生产环境建议搭配 sidecar 或 VPN

运行测试

go test -v ./...

项目结构

mrpc/
├── client.go          # RPC 客户端
├── server.go          # RPC 服务端(反射注册 + TCP 监听)
├── protocol.go        # 二进制线协议(帧 + Request/Response)
├── codec.go           # Codec 接口 + msgpack 实现
├── pool.go            # 分级缓冲池(Tiered Pool)
├── health.go          # 健康检查(服务端 + 客户端检查器)
├── cmd/main.go        # 可运行的示例程序
├── *_test.go          # 单元测试 & 集成测试 & 示例测试

License

MIT

Documentation

Overview

Example (ErrorHandling)

Example_errorHandling 演示各种错误场景的处理。

package main

import (
	"fmt"
	"net"
	"time"

	"github.com/23jdd/mrpc"
)

// Calculator 是一个示例 RPC 服务实现。
type Calculator struct{}

// MultiplyReq 乘法请求参数。
// 字段首字母必须大写(msgpack 序列化要求)。
type MultiplyReq struct {
	A int
	B int
}

// MultiplyReply 乘法响应结果。
type MultiplyReply struct {
	Product int
}

// Multiply 乘法 RPC 方法。
//
// 签名必须满足 func(req T, reply *U) error。
//   - req:  请求参数(可以是值类型或指针类型,msgpack 可反序列化即可)
//   - reply: 响应参数,必须为指针(以便 server 将结果写入)
//   - error: 方法执行错误,为 nil 时表示成功
//
// 边界条件:
//   - req 类型错误时 msgpack 解码会失败
//   - reply 为 nil 时会导致 panic
//   - 方法中若 panic 未被 recover,会导致连接关闭
func (c *Calculator) Multiply(req MultiplyReq, reply *MultiplyReply) error {

	reply.Product = req.A * req.B
	return nil
}

func main() {
	lis, _ := net.Listen("tcp", "127.0.0.1:0")
	defer lis.Close()

	server := mrpc.NewServer(lis)
	server.Register("Calculator", &Calculator{})
	go server.Run()

	_, port, _ := net.SplitHostPort(lis.Addr().String())
	var portNum int
	fmt.Sscanf(port, "%d", &portNum)

	client := mrpc.NewClient("127.0.0.1", portNum)
	defer client.Close()
	time.Sleep(50 * time.Millisecond)

	// 场景1:调用不存在的方法 → 服务端关闭连接,客户端收到网络错误
	var reply MultiplyReply
	err := client.Call("Calculator.NoSuchMethod", &MultiplyReq{}, &reply)
	if err != nil {
		fmt.Println("unknown method:", err != nil)
	}

	// 场景2:调用不存在的服务 → 同上
	err = client.Call("NoService.Method", &MultiplyReq{}, &reply)
	if err != nil {
		fmt.Println("unknown service:", err != nil)
	}

	// 场景3:传入 nil reply → msgpack 无法解码,通常不会有问题(nil reply 跳过解码)
	err = client.Call("Calculator.Multiply", &MultiplyReq{A: 1, B: 2}, nil)
	fmt.Println("nil reply, err:", err)

}
Output:
unknown method: true
unknown service: true
nil reply, err: <nil>
Example (HealthCheck)

Example_healthCheck 演示健康检查功能。

package main

import (
	"fmt"
	"log"
	"net"
	"time"

	"github.com/23jdd/mrpc"
)

// Calculator 是一个示例 RPC 服务实现。
type Calculator struct{}

// MultiplyReq 乘法请求参数。
// 字段首字母必须大写(msgpack 序列化要求)。
type MultiplyReq struct {
	A int
	B int
}

// MultiplyReply 乘法响应结果。
type MultiplyReply struct {
	Product int
}

// Multiply 乘法 RPC 方法。
//
// 签名必须满足 func(req T, reply *U) error。
//   - req:  请求参数(可以是值类型或指针类型,msgpack 可反序列化即可)
//   - reply: 响应参数,必须为指针(以便 server 将结果写入)
//   - error: 方法执行错误,为 nil 时表示成功
//
// 边界条件:
//   - req 类型错误时 msgpack 解码会失败
//   - reply 为 nil 时会导致 panic
//   - 方法中若 panic 未被 recover,会导致连接关闭
func (c *Calculator) Multiply(req MultiplyReq, reply *MultiplyReply) error {

	reply.Product = req.A * req.B
	return nil
}

func main() {
	lis, _ := net.Listen("tcp", "127.0.0.1:0")
	defer lis.Close()

	server := mrpc.NewServer(lis)
	server.Register("Calculator", &Calculator{})
	// 注册健康检查服务
	server.Register("Health", mrpc.RegisterHealth())
	go server.Run()

	_, port, _ := net.SplitHostPort(lis.Addr().String())
	var portNum int
	fmt.Sscanf(port, "%d", &portNum)

	client := mrpc.NewClient("127.0.0.1", portNum)
	defer client.Close()
	time.Sleep(50 * time.Millisecond)

	// 调用健康检查
	var healthReply mrpc.HealthReply
	err := client.Call("Health.Check", &mrpc.HealthRequest{}, &healthReply)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("server healthy:", healthReply.Ok)

	// 启动周期性健康检查(后台 goroutine)
	checker := mrpc.NewHealthChecker(5*time.Second, 2*time.Second)
	checker.Start(client, 3, func(err error) {
		fmt.Println("health check failed:", err)
	})
	defer checker.Stop()

}
Output:
server healthy: true
Example (ServerAndClient)

Example_serverAndClient 演示从服务注册到客户端调用的完整流程。

流程:

  1. 创建 net.Listener 监听 TCP 端口
  2. 创建 Server 并注册服务实现
  3. 在后台 goroutine 启动服务端
  4. 创建 Client 发起 RPC 调用
  5. 解析响应并打印结果

注意事项:

  • 单向非流式:每次调用发一个请求、收一个响应,连接随之关闭(server 端)
  • Client 默认使用 msgpack 编解码,连接在多次 Call 之间复用
  • Call 的 argv 和 reply 参数都必须为指针,否则编解码失败
package main

import (
	"fmt"
	"log"
	"net"
	"time"

	"github.com/23jdd/mrpc"
)

// Calculator 是一个示例 RPC 服务实现。
type Calculator struct{}

// MultiplyReq 乘法请求参数。
// 字段首字母必须大写(msgpack 序列化要求)。
type MultiplyReq struct {
	A int
	B int
}

// MultiplyReply 乘法响应结果。
type MultiplyReply struct {
	Product int
}

// Multiply 乘法 RPC 方法。
//
// 签名必须满足 func(req T, reply *U) error。
//   - req:  请求参数(可以是值类型或指针类型,msgpack 可反序列化即可)
//   - reply: 响应参数,必须为指针(以便 server 将结果写入)
//   - error: 方法执行错误,为 nil 时表示成功
//
// 边界条件:
//   - req 类型错误时 msgpack 解码会失败
//   - reply 为 nil 时会导致 panic
//   - 方法中若 panic 未被 recover,会导致连接关闭
func (c *Calculator) Multiply(req MultiplyReq, reply *MultiplyReply) error {

	reply.Product = req.A * req.B
	return nil
}

func main() {
	// 1. 创建 TCP listener
	lis, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		log.Fatal(err)
	}
	defer lis.Close()

	// 2. 创建 Server 并注册服务
	server := mrpc.NewServer(lis)
	if err := server.Register("Calculator", &Calculator{}); err != nil {
		log.Fatal(err)
	}

	// 3. 后台启动服务端
	go server.Run()

	// 4. 创建客户端(连接服务端监听的端口)
	_, port, _ := net.SplitHostPort(lis.Addr().String())
	var portNum int
	fmt.Sscanf(port, "%d", &portNum)

	client := mrpc.NewClient("127.0.0.1", portNum)
	defer client.Close()

	// 给服务端一点时间
	time.Sleep(50 * time.Millisecond)

	// 5. 发起 RPC 调用
	req := &MultiplyReq{A: 7, B: 8}
	var reply MultiplyReply
	if err := client.Call("Calculator.Multiply", req, &reply); err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%d * %d = %d\n", req.A, req.B, reply.Product)
}
Output:
7 * 8 = 56

Index

Examples

Constants

View Source
const MaxPayloadSize = 10 << 20 // 10 MB

Variables

View Source
var (
	// ErrClosed 表示连接已关闭。
	ErrClosed = errors.New("mrpc: connection has been closed")
	// ErrShutdown 表示客户端已手动关闭。
	ErrShutdown = errors.New("mrpc: client is shut down")
)
View Source
var DefaultPool = NewTieredPool(
	128,
	512,
	2048,
	8192,
	32768,
	65536,
	262144,
	524288,
	1048576,
	MaxPayloadSize,
)

DefaultPool 是协议层内部使用的默认分级缓冲池。 覆盖从 128B 到 10MB 的常见 RPC 负载大小,减少 ReadFrame 和 readString 的内存分配。

调用方也可以直接使用 DefaultPool 管理自己的缓冲区:

buf := mrpc.DefaultPool.Get(4096)
defer mrpc.DefaultPool.Put(buf)
View Source
var ErrMaxPayload = errors.New("mrpc: payload exceeds maximum size")

Functions

func PutFrame

func PutFrame(payload []byte)

PutFrame 将从 ReadFrame 获取的帧 buffer 归还给 DefaultPool。 调用方在完成帧数据的解码后应调用此函数。 与 DefaultPool.Put 等价,方便配对使用:ReadFrame / PutFrame。

func ReadFrame

func ReadFrame(r io.Reader) ([]byte, error)

func RegisterHealth

func RegisterHealth() *healthService

RegisterHealth 在服务端注册心跳检测方法。

用法:

server.Register("Health", mrpc.RegisterHealth())

这会注册一个 Health.Check 方法,客户端可周期性调用以检测连通性。

返回值是指向内部实现的指针,需作为 Register 的 target 参数。

func SendRequest

func SendRequest(w io.Writer, req *Request) error

func SendResponse

func SendResponse(w io.Writer, resp *Response) error

func WriteFrame

func WriteFrame(w io.Writer, payload []byte) error

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client 是 RPC 客户端,支持单向非流式调用。

典型用法:

client := mrpc.NewClient("localhost", 8080)
defer client.Close()
var reply ReplyType
err := client.Call("Service.Method", &Request{...}, &reply)

Call 会自动维护 TCP 长连接并在首次调用或断线时重连。

func NewClient

func NewClient(address string, port int) *Client

NewClient 创建一个 RPC 客户端。

参数:

  • address: 服务端 IP 或主机名(支持 IPv4/IPv6)
  • port: 服务端端口号

边界条件:

  • address 为空时 net.Dial 会返回错误(在 Call 时暴露)
  • port <= 0 或 >65535 时 net.Dial 会返回错误

func NewClinet

func NewClinet(address string, port int) *Client

NewClinet 是 NewClient 的别名,保留以兼容旧代码。 新代码请使用 NewClient。

func (*Client) Call

func (c *Client) Call(method string, argv any, reply any) error

Call 执行一次单向非流式 RPC 调用。

流程:编码 argv → 发送请求 → 接收响应 → 解码到 reply。 若尚未建立连接,会自动调用 Dial 建立 TCP 连接。 连接会在多次 Call 之间复用(长连接)。

参数:

  • method: 方法名,格式 "ServiceName.MethodName"
  • argv: 请求参数指针(msgpack 需要指针才能编码)
  • reply: 响应参数指针,结果将解码到此

返回值:

  • 成功时返回 nil
  • 网络错误、编解码错误、服务端返回的错误均通过 error 返回

边界条件:

  • argv 必须是指针或可序列化类型,否则 Encode 失败
  • reply 必须是指针,否则 Decode 无法写入
  • 并发调用 Call 不安全(共用同一连接),需要外部加锁

func (*Client) Close

func (c *Client) Close() error

Close 关闭客户端连接并标记为 shut down 状态。

关闭后再次调用 Call 会返回 ErrShutdown。 对已关闭的客户端调用 Close 是安全的(幂等)。

func (*Client) Dial

func (c *Client) Dial() error

Dial 建立到服务端的 TCP 连接。

若已有连接,先关闭旧连接再建立新连接。 多次调用 Dial 是安全的。

type Codec

type Codec interface {
	Encode(v any) ([]byte, error)
	Decode(data []byte, v any) error
}

Codec 定义编解码器接口,负责请求/响应体的序列化与反序列化。

实现者需保证 Encode/Decode 的线程安全性(本库在服务端每个连接 使用独立 Codec 实例,客户端单连接复用同一实例)。

type HealthChecker

type HealthChecker struct {
	// contains filtered or unexported fields
}

HealthChecker 提供客户端到服务端的周期性健康检查能力。

通过注册 MRPC 方法 "Health.Check",客户端可以周期性调用此方法 来检测服务端是否可达。

func NewHealthChecker

func NewHealthChecker(interval, timeout time.Duration) *HealthChecker

NewHealthChecker 创建一个健康检查器。

参数:

  • interval: 健康检查间隔(必须 >0,建议 5s~60s)
  • timeout: 每次检查的超时时间(必须 >0 且 ≤ interval)

func (*HealthChecker) Start

func (hc *HealthChecker) Start(client *Client, maxFailures int, onFailure func(error))

Start 在后台启动心跳循环,定期向指定客户端发起健康检查调用。

当连续 maxFailures 次检查失败时,调用 onFailure 回调。

参数:

  • client: 已连接的 RPC 客户端
  • maxFailures: 连续失败多少次后触发回调(建议 ≥1)
  • onFailure: 失败回调,传入最后一次错误

func (*HealthChecker) Stop

func (hc *HealthChecker) Stop()

Stop 停止心跳循环。

type HealthReply

type HealthReply struct {
	Ok bool
}

HealthReply 是心跳检测的响应参数(体)。 Ok 为 true 表示服务健康。

type HealthRequest

type HealthRequest struct{}

HealthRequest 是心跳检测的请求参数(体)。 可根据需要扩展字段。

type MsgCodec

type MsgCodec struct{}

MsgCodec 是基于 msgpack 的 Codec 实现。

func NewMsgCodec

func NewMsgCodec() *MsgCodec

NewMsgCodec 创建一个新的 MsgCodec 实例。

func (*MsgCodec) Decode

func (mc *MsgCodec) Decode(data []byte, v any) error

Decode 使用 msgpack 反序列化 data 到 v。

func (*MsgCodec) Encode

func (mc *MsgCodec) Encode(v any) ([]byte, error)

Encode 使用 msgpack 序列化 v。

type RPCMethod

type RPCMethod struct {
	ReqType   reflect.Type
	ReplyType reflect.Type
}

RPCMethod 描述找到的符合 func(Req, *Reply) error 签名的方法。 ReqType 为请求参数类型,ReplyType 为响应参数类型(已保证为指针)。

type Request

type Request struct {
	ServiceMethod string // "Calculator.Add"
	Seq           uint64 // 请求 ID,用于异步匹配
	Argv          []byte // 序列化后的参数
}

func NewRequest

func NewRequest(method string, seq uint64, argv []byte) *Request

func ReceiveRequest

func ReceiveRequest(r io.Reader) (*Request, error)

func (*Request) Decode

func (re *Request) Decode(data []byte) error

func (*Request) Encode

func (re *Request) Encode() ([]byte, error)

Encode

type Response

type Response struct {
	Seq   uint64 // 对应请求 ID
	Reply []byte // 序列化后的返回值
	Error string // 错误信息
}

func NewResponse

func NewResponse(seq uint64, reply []byte, err string) *Response

func ReceiveResponse

func ReceiveResponse(r io.Reader) (*Response, error)

func (*Response) Decode

func (rs *Response) Decode(data []byte) error

func (*Response) Encode

func (rs *Response) Encode() ([]byte, error)

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server 是一个基于 TCP 的反射型 RPC 服务端。 通过 Register 注册服务实现,Run 启动监听循环,对每个连接 在独立 goroutine 中处理单次单向非流式调用。

func NewServer

func NewServer(lis net.Listener) *Server

NewServer 创建一个 RPC 服务端,绑定到给定的 net.Listener。 lis 必须非 nil,否则会在 Run 时 panic。

func (*Server) NewConn

func (s *Server) NewConn(con net.Conn, codec Codec) *connect

NewConn 从 TCP 连接创建一个 Connect 对象。

func (*Server) Register

func (s *Server) Register(name string, target any) error

Register 从结构体指针中找出所有签名类似 func(request, *reply) error 的方法并注册。

参数:

  • name: 服务名,调用时使用 "name.MethodName" 格式
  • target: 服务实现,必须为指向 struct 的指针

边界条件:

  • target 必须是 *struct 指针,否则返回错误
  • 只注册满足 func(req T, reply *U) error 签名的方法
  • 同名服务重复注册会覆盖之前的方法
  • 空结构体或无符合方法时不会报错(直接返回 nil)

func (*Server) Registery

func (s *Server) Registery(name string, target any) error

Registery 是 Register 的别名,保留以兼容旧代码。 新代码请使用 Register。

func (*Server) Run

func (s *Server) Run()

Run 启动服务端主循环:在调用方 goroutine 中阻塞 Accept 新连接, 并为每个连接启动一个新 goroutine 调用 Handler。 当 lis.Accept 返回 net.ErrClosed 或其它不可恢复错误时退出。

type TieredPool

type TieredPool struct {
	// contains filtered or unexported fields
}

TieredPool 分级缓冲池:按不同容量分桶复用 []byte,减少内存浪费与分配。 TieredPool is a collection of sync.Pools of different capacities, designed to reuse []byte slices of varying sizes while minimizing memory waste.

func NewTieredPool

func NewTieredPool(capacities ...int) *TieredPool

NewTieredPool 按给定(升序)容量列表创建分级缓冲池。 capacities 必须非空、严格递增且全部大于 0,否则函数会 panic;构造函数会复制参数, 因此调用方之后修改原切片不会影响池配置。 NewTieredPool New creates a new TieredPool with the given capacities. Each capacity defines a pool of buffers with that exact capacity. The capacities slice must be sorted in ascending order.

func (*TieredPool) Get

func (tp *TieredPool) Get(size int) []byte

Get 取出一个长度为 size、容量不小于 size 的缓冲(从能容纳的最小桶取)。 size=0 合法并使用最小桶;size<0 会 panic;size 超过最大桶时直接分配且不会被 Put 复用。 Get returns a []byte of length size with capacity at least size. The buffer is taken from the smallest pool whose capacity >= size. If no pool is large enough, a new buffer is allocated without pooling.

func (*TieredPool) Put

func (tp *TieredPool) Put(buf []byte)

Put 归还缓冲:只有容量与某个桶完全匹配时才复用,其他缓冲直接丢弃。 精确匹配可以保证桶内缓冲始终满足该桶的容量约束。 buf 可以是 nil;归还后调用方不得再访问它。池不会清除底层字节,敏感数据应由调用方先覆盖。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL