根据golang中的字节长度分割字符串

时间:2018-09-13 23:27:57

标签: http go http-headers

http请求标头的长度限制为4k。 我想基于此限制拆分要包含在标题中的字符串。 我应该先使用[]byte(str)进行拆分,然后对每个拆分部分使用string([]byte)转换回字符串吗? 有没有更简单的方法?

1 个答案:

答案 0 :(得分:4)

在Go中,字符串实际上只是字节序列和indexing a string produces bytes。因此,您可以通过将字符串切成4kB子字符串来简单地将其拆分为子字符串。

但是,由于UTF-8字符可以跨越多个字节,因此您有可能在一个字符序列的中间进行拆分。如果拆分后的字符串在解码之前总是在另一端以相同的顺序再次连接在一起,那么这不是问题,但是如果尝试分别解码每个字符串,则可能会导致无效的前导或尾随字节序列。如果您想避免这种情况,可以使用unicode/utf8包检查是否在有效的前导字节上拆分,如下所示:

package httputil

import "unicode/utf8"

const maxLen = 4096

func SplitHeader(longString string) []string {
    splits := []string{}

    var l, r int
    for l, r = 0, maxLen; r < len(longString); l, r = r, r+maxLen {
        for !utf8.RuneStart(longString[r]) {
            r--
        }
        splits = append(splits, longString[l:r])
    }
    splits = append(splits, longString[l:])
    return splits
}

直接切片字符串比转换回[]byte更有效,因为既然string是不可变的,而[]byte不是不变的,则必须将数据复制到新的内存中转换后,花费O(n)时间(双向!),而切片字符串只是返回一个新的字符串标头,该标头由与原始数组相同的数组作为后盾(采用恒定时间)。