You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将&mut BytesMut传递给接收&Bytes参数的函数?

如何将&mut BytesMut传递给接收&Bytes参数的函数?

嗨,这个问题我之前也碰到过,给你说几个实用的解决办法,看你需求选就行~

首先得搞清楚:BytesMut 是可变的字节缓冲区,Bytes 是不可变的、可安全共享的字节容器,两者都是bytes工具集里的类型,但直接传&mut BytesMut给要&Bytes的函数肯定是不行的,得做些转换。

方法一:冻结BytesMut得到Bytes(一次性使用场景)

如果你的BytesMut用完这次就不需要再修改或者使用了,那直接用freeze()方法就搞定了:

let mut buf = BytesMut::from(&b"hello world"[..]);
// 调用freeze()消耗掉buf,得到Bytes
let bytes = buf.freeze();
parse_len(&bytes);
// 注意:这里buf已经不能再用了,因为已经被冻结消耗了

这个方法没有复制开销,但是代价是原BytesMut就废了,适合你处理完这部分内容就不再需要原缓冲区的场景。

方法二:复制内容生成临时Bytes(需要保留原BytesMut的场景)

如果你之后还要继续操作原来的BytesMut,那可以先把它的内容复制一份,用副本生成Bytes:

let mut buf = BytesMut::from(&b"hello world"[..]);
// 从buf的内容复制出一份Bytes
let temp_bytes = Bytes::copy_from_slice(&buf);
parse_len(&temp_bytes);
// 这里buf还能继续用,比如继续写入数据
buf.extend_from_slice(&b" more data"[..]);

不过这个方法会有数据复制的开销,如果你的数据量特别大,可能会影响性能,得权衡着用。

方法三:修改目标函数的参数类型(最优解,推荐!)

其实最省事的办法是直接改parse_len的参数,把&Bytes改成&[u8]。因为不管是Bytes还是BytesMut,都能自动解引用成&[u8],这样函数的通用性一下子就上去了,不管传&Bytes、&BytesMut甚至直接传普通的&[u8]都能兼容:

// 修改后的函数
fn parse_len(bytes: &[u8]) -> usize {
    // 原来的逻辑完全不用改,比如取第一个字节判断类型,后面的解析长度
    let msg_type = bytes[0];
    // 假设长度是后面4个字节转成usize
    let len_bytes = &bytes[1..5];
    u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize
}

// 调用的时候直接传&mut buf或者&buf都可以
let mut buf = BytesMut::from(&b"\x01\x00\x00\x00\x0ahello"[..]);
parse_len(&buf); // 直接传&BytesMut就行
// 传&Bytes也照样能用
let bytes = Bytes::from(&b"\x02\x00\x00\x00\x05world"[..]);
parse_len(&bytes);

这个方法既没有复制开销,又不用做各种转换,简直是一劳永逸的办法,强烈推荐!

备注:内容来源于stack exchange,提问作者ivanbgd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 17:00:27