高效内存方式实现Golang []byte追加操作
高效内存方式实现Golang []byte追加操作
我有一种感觉,dump = append([]byte(fmt.Sprintf( ... 这行代码在内存使用上不够高效,因为我不知道字节的大小,我使用了 fmt 并且将字符串转换为字节。
请问如何改进这一点?
谢谢
dump, err := httputil.DumpResponse(res, true)
if err != nil {
return err
}
met := http.MethodGet
if res.request.Method != "" {
met = res.request.Method
}
uri := res.request.RequestURI
if uri == "" {
uri = res.request.URL.RequestURI()
}
dump = append([]byte(fmt.Sprintf("%s %s HTTP/%d.%d\nHost: %s\n",
met,
uri,
res.request.ProtoMajor,
res.request.ProtoMinor,
res.request.Host,
)), dump...)
更多关于高效内存方式实现Golang []byte追加操作的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
要高效地实现 []byte 追加操作,避免不必要的内存分配和类型转换,可以使用 bytes.Buffer 或直接使用 append 配合 strconv 等低开销函数。以下是改进后的代码示例:
import (
"bytes"
"net/http/httputil"
"strconv"
)
func dumpResponse(res *http.Response) error {
dump, err := httputil.DumpResponse(res, true)
if err != nil {
return err
}
met := http.MethodGet
if res.Request.Method != "" {
met = res.Request.Method
}
uri := res.Request.RequestURI
if uri == "" {
uri = res.Request.URL.RequestURI()
}
var buf bytes.Buffer
buf.WriteString(met)
buf.WriteByte(' ')
buf.WriteString(uri)
buf.WriteString(" HTTP/")
buf.WriteString(strconv.Itoa(res.Request.ProtoMajor))
buf.WriteByte('.')
buf.WriteString(strconv.Itoa(res.Request.ProtoMinor))
buf.WriteString("\nHost: ")
buf.WriteString(res.Request.Host)
buf.WriteByte('\n')
// 将头部和原始dump合并
headerBytes := buf.Bytes()
result := make([]byte, len(headerBytes) + len(dump))
copy(result, headerBytes)
copy(result[len(headerBytes):], dump)
// 使用result继续后续操作
_ = result // 替换为实际使用
return nil
}
或者使用更直接的 append 方式,避免中间字符串转换:
func dumpResponse(res *http.Response) error {
dump, err := httputil.DumpResponse(res, true)
if err != nil {
return err
}
met := http.MethodGet
if res.Request.Method != "" {
met = res.Request.Method
}
uri := res.Request.RequestURI
if uri == "" {
uri = res.Request.URL.RequestURI()
}
// 预分配足够空间
result := make([]byte, 0, len(met)+len(uri)+50+len(dump))
result = append(result, met...)
result = append(result, ' ')
result = append(result, uri...)
result = append(result, " HTTP/"...)
result = append(result, strconv.Itoa(res.Request.ProtoMajor)...)
result = append(result, '.')
result = append(result, strconv.Itoa(res.Request.ProtoMinor)...)
result = append(result, "\nHost: "...)
result = append(result, res.Request.Host...)
result = append(result, '\n')
result = append(result, dump...)
// 使用result继续后续操作
_ = result // 替换为实际使用
return nil
}
这两种方式都避免了 fmt.Sprintf 产生的临时字符串和 []byte() 转换带来的额外内存分配,通过直接操作字节切片或使用缓冲区来提高内存效率。


