这是另一个变体游乐场。与其他答案相比,它在速度和内存方面的效率要高得多。如果您想在这里运行基准测试,它们就是benchmarks。一般来说,它比以前的版本快 5 倍,无论如何都是最快的答案。


func Chunks(s string, chunkSize int) []string {

    if len(s) == 0 {

        return nil

    }

    if chunkSize >= len(s) {

        return []string{s}

    }

    var chunks []string = make([]string, 0, (len(s)-1)/chunkSize+1)

    currentLen := 0

    currentStart := 0

    for i := range s {

        if currentLen == chunkSize {

            chunks = append(chunks, s[currentStart:i])

            currentLen = 0

            currentStart = i

        }

        currentLen++

    }

    chunks = append(chunks, s[currentStart:])

    return chunks

}

请注意,索引指向迭代字符串时符文的第一个字节。符文占用 1 到 4 个字节。切片还将字符串视为字节数组。


以前的较慢算法


代码在这里操场。从字节到符文再到字节的转换实际上需要很多时间。所以最好使用答案顶部的快速算法。


func ChunksSlower(s string, chunkSize int) []string {

    if chunkSize >= len(s) {

        return []string{s}

    }

    var chunks []string

    chunk := make([]rune, chunkSize)

    len := 0

    for _, r := range s {

        chunk[len] = r

        len++

        if len == chunkSize {

            chunks = append(chunks, string(chunk))

            len = 0

        }

    }

    if len > 0 {

        chunks = append(chunks, string(chunk[:len]))

    }

    return chunks

}

请注意,这两种算法以不同的方式处理无效的 UTF-8 字符。当第二个用utf8.RuneError符号 ( '\uFFFD')替换它们时,第一个按原样处理它们,该符号在 UTF-8 中具有以下十六进制表示:efbfbd。