猿问

符文和字节(切片)之间的转换

Go 允许从runeto转换byte。rune但是对于is的底层类型int32(因为 Go 使用 UTF-8),对于byteis uint8,转换因此会导致信息丢失。但是,无法从符文转换为[]byte.


var b byte = '©'

bs := []byte(string('©'))

fmt.Println(b)

fmt.Println(bs)


// Output

169

[194 169]


为什么 Go 允许转换 from runetobyte而不是runeto []byte?


蝴蝶不菲
浏览 176回答 3
3回答

精慕HU

Go 支持从runeto的转换,byte就像它对所有数字类型对所做的那样。如果不允许转换,那将是一个令人惊讶的特殊int32情况byte。但底层的类型rune是int32(因为 Go 使用 UTF-8)这遗漏了一个重要的细节:rune是int32. 它们是同一类型。确实,底层类型是runeis int32,但这是因为runeandint32是相同的类型,而内置类型的底层类型是类型本身。Unicode 代码点作为int32值的表示与 UTF-8 编码无关。因此,转换会导致信息丢失是的,数字类型之间的转换可能会导致信息丢失。这是 Go 中的转换必须是显式的原因之一。请注意,该语句var b byte = '©'不进行任何转换。该表达式'@'是一个无类型的常量。如果分配无类型常量导致信息丢失,编译器会报告错误。例如,该语句var b byte = '世'会导致编译错误。该语言中的所有 UTF-8 编码功能都与string类型有关。UTF-8 感知转换都是与string类型之间的。可以支持转换,[]byte(numericType)但这会将 UTF-8 编码带到string类型之外。Go 作者对包含string(numericType)转换感到遗憾,因为它在实践中不是很有用,而且转换也不是某些人所期望的。库函数是该功能的更好位置。

撒科打诨

是的,可以从 rune 转换为 []byte(例如通过字节)并再次转换回来。package mainimport "fmt"func main() {    var b byte = '©'    bs := []byte{b}    fmt.Printf("%T %v\n", b, b)   // uint8 169    fmt.Printf("%T %v\n", bs, bs) // []uint8 [169]    s := string(bs[0]) // s := string(b) works too.    r2 := rune(s[0]) // r2 := rune(b) works too.    fmt.Printf("%T %v\n", s, s) // string ©    fmt.Printf("%T %v\n", r2, r2) // int32 169}

摇曳的蔷薇

这种行为的原因与合法的原因相同var b int32b = 1000000fmt.Printf("%b\n", b)fmt.Printf("%b", uint8(b))// Output:// 11110100001001000000// 1000000当您将具有较大内存占用的类型的数据放入具有较小内存占用的类型时,您应该期望转换为松散数据。此外,对于 a 编码,rune您可以使用EncodeRune,它确实使用 a []byte。
随时随地看视频慕课网APP

相关分类

Go
我要回答