如何将字节缓冲区中以null结尾的字符串转换为Go中的字符串?

kna*_*arf 7 c string go

这个:

label := string([]byte{97, 98, 99, 0, 0, 0, 0})
fmt.Printf("%s\n", label)
Run Code Online (Sandbox Code Playgroud)

^@是(是空字节):

go run test.go 
abc^@^@^@
Run Code Online (Sandbox Code Playgroud)

aze*_*nik 11

请注意,第一个答案仅适用于在null终止符后仅运行零的字符串; 然而,一个正确的C风格的以null结尾的字符串在第一个字符串结尾,\0即使它后面跟着垃圾.例如,[]byte{97,98,99,0,99,99,0}应该解析为abc,而不是abc^@cc.

要正确解析它,请string.Index按如下方式使用以查找第一个 \0并使用它来对原始字节切片进行切片:

package main

import (
    "fmt"
    "strings"
)

func main() {
    label := []byte{97,98,99,0,99,99,0}
    nullIndex := strings.Index(string(label), "\x00")
    if (nullIndex < 0) {
        fmt.Println("Buffer did not hold a null-terminated string")
        os.Exit(1)
    }
    fmt.Println(string(label[:nullIndex]))
}
Run Code Online (Sandbox Code Playgroud)

编辑:打印缩短版本[]byte而不是作为string.感谢@serbaut的捕获.

编辑2:没有处理没有空终止符的缓冲区的错误情况.感谢@snap的捕获.

  • 不应该是字符串(标签[:bytes.IndexByte(label,0)])? (2认同)

Eri*_*ren 9

在Go的syscall包中隐藏了这个函数,它找到第一个空字节([] byte {0})并返回长度.我假设它被称为C-Length的clen.

对不起,我对这个答案迟了一年,但我觉得它比其他两个简单得多(没有不必要的进口等)

func clen(n []byte) int {
    for i := 0; i < len(n); i++ {
        if n[i] == 0 {
            return i
        }
    }
    return len(n)
}
Run Code Online (Sandbox Code Playgroud)

所以,

label := []byte{97, 98, 99, 0, 0, 0, 0}
s := label[:clen(label)]
fmt.Println(string(s))
Run Code Online (Sandbox Code Playgroud)

^所说的是设置slabel从开头到索引的字节切片clen(label).

结果将是abc3的长度.


jor*_*lli 5

使用strings包.

package main

import (
    "fmt"
    "strings"
)

func main() {
    label := string([]byte{97, 98, 99, 0, 0, 0, 0})
    fmt.Println(strings.TrimSpace(label))
}
Run Code Online (Sandbox Code Playgroud)

  • 我用过`strings.TrimRight(标签,"\ x00")`,谢谢! (5认同)
  • 这会修剪空间,这可能是字符串的重要部分. (2认同)