高效内存方式实现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

1 回复

更多关于高效内存方式实现Golang []byte追加操作的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


要高效地实现 []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() 转换带来的额外内存分配,通过直接操作字节切片或使用缓冲区来提高内存效率。

回到顶部