我想将字符串分配给字节数组:
var arr [20]byte
str := "abc"
for k, v := range []byte(str) {
arr[k] = byte(v)
}
有别的方法吗?
str
的长度大于 arr
的长度,那么您将收到“索引超出范围”错误。
[]byte(“abc”)
将字符串设置为字节切片。请参阅 stackoverflow.com/a/62740786/12817546.string(b)
或 fmt.Sprintf("%s", b)
将字节切片设置为字符串。见stackoverflow.com/a/62725637/12817546。
安全简单:
[]byte("Here is a string....")
要将字符串转换为字节切片,string -> []byte
:
[]byte(str)
要将数组转换为切片,[20]byte -> []byte
:
arr[:]
要将字符串复制到数组,string -> [20]byte
:
copy(arr[:], str)
与上面相同,但首先将字符串显式转换为切片:
copy(arr[:], []byte(str))
内置的复制功能仅从切片复制到切片。
数组是“底层数据”,而切片是“底层数据的视口”。
使用 [:] 使数组符合切片的条件。
字符串不符合可以复制到的切片的条件,但它可以作为可以复制的切片(字符串是不可变的)。
如果字符串太长,则 copy 将只复制适合的部分字符串(然后可能只复制部分多字节符文,这将破坏结果字符串的最后一个符文)。
这段代码:
var arr [20]byte
copy(arr[:], "abc")
fmt.Printf("array: %v (%T)\n", arr, arr)
...给出以下输出:
array: [97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] ([20]uint8)
我还在 Go Playground
b[i] = []byte("A")[0]
有效,但 b[i] = 'A'
最终变得更干净。
b[1] = '本'
[]byte(str)
是否使用 make()
创建新的底层数组?还是只是将指针副本返回到原始字符串。
[]byte(str)
调用了 runtime.stringtoslicebyte
函数。 stringtoslicebyte
将在需要时分配内存,然后调用 copy
。见:string.go。 copy
函数循环复制字节。
例如,
package main
import "fmt"
func main() {
s := "abc"
var a [20]byte
copy(a[:], s)
fmt.Println("s:", []byte(s), "a:", a)
}
输出:
s: [97 98 99] a: [97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
s
,`copy函数不傻。 Appending to and copying slices:“复制的元素数量是 len(src) 和 len(dst) 中的最小值。”
小菜一碟:
arr := []byte("That's all folks!!")
[]byte
优于数组 [20]byte
。根据最佳实践,答案是正确的;如果规范或代码需要数组,则使用 copy
代替(请参阅此线程中其他地方的示例)。
我觉得这样更好。。
package main
import "fmt"
func main() {
str := "abc"
mySlice := []byte(str)
fmt.Printf("%v -> '%s'",mySlice,mySlice )
}
在这里检查:http://play.golang.org/p/vpnAWHZZk7
Go,将字符串转换为字节切片
您需要一种将 []string 转换为 []byte 类型的快速方法。用于将文本数据存储到随机访问文件或其他需要输入数据为 []byte 类型的数据操作的情况。
package main
func main() {
var s string
//...
b := []byte(s)
//...
}
这在使用 ioutil.WriteFile 时很有用,它接受字节切片作为其数据参数:
WriteFile func(filename string, data []byte, perm os.FileMode) error
另一个例子
package main
import (
"fmt"
"strings"
)
func main() {
stringSlice := []string{"hello", "world"}
stringByte := strings.Join(stringSlice, " ")
// Byte array value
fmt.Println([]byte(stringByte))
// Corresponding string value
fmt.Println(string([]byte(stringByte)))
}
输出:
[104 101 108 108 111 32 119 111 114 108 100] 你好,世界
请检查链接 playground
最终创建了特定于数组的方法来执行此操作。很像 encoding/binary 包,每个 int 类型都有特定的方法。例如 binary.BigEndian.PutUint16([]byte, uint16)
。
func byte16PutString(s string) [16]byte {
var a [16]byte
if len(s) > 16 {
copy(a[:], s)
} else {
copy(a[16-len(s):], s)
}
return a
}
var b [16]byte
b = byte16PutString("abc")
fmt.Printf("%v\n", b)
输出:
[0 0 0 0 0 0 0 0 0 0 0 0 0 97 98 99]
请注意我想要在左侧而不是右侧进行填充。
http://play.golang.org/p/7tNumnJaiN
byte16PutString
是内置 copy
函数的一种重新实现,它只支持创建新数组而不是使用现有数组。 copy
具有特殊的编译器支持,因此它可以处理不同类型的参数,并且它可能具有真正的高性能实现。此外,OP 的问题询问关于将字符串写入现有数组,而不是分配新数组,尽管大多数其他答案似乎也忽略了这一点......
数组是值......切片更像是指针。那就是 [n]type
与 []type
不兼容,因为它们本质上是两个不同的东西。您可以使用 arr[:]
获取指向数组的切片,该切片返回具有 arr
作为后备存储的切片。
将例如 []byte
的切片转换为 [20]byte
的一种方法是实际分配一个 [20]byte
,您可以使用 var [20]byte
来执行此操作(因为它是一个值......不需要 make
)然后复制数据进入它:
buf := make([]byte, 10)
var arr [10]byte
copy(arr[:], buf)
本质上,许多其他答案出错的是 []type
不是数组。
[n]T
和 []T
是完全不同的东西!
当使用反射时,[]T
不是一种数组,而是一种 Slice,而 [n]T
是一种数组。
您也不能使用 map[[]byte]T
,但可以使用 map[[n]byte]T
。
这有时会很麻烦,因为很多函数都在 []byte
上运行,而有些函数返回 [n]byte
(最值得注意的是 crypto/*
中的哈希函数)。例如,sha256 哈希是 [32]byte
而不是 []byte
,因此当初学者尝试将其写入文件时,例如:
sum := sha256.Sum256(data)
w.Write(sum)
他们会得到一个错误。的正确方法是使用
w.Write(sum[:])
然而,你想要的是什么?只是按字节访问字符串?您可以使用以下方法轻松地将 string
转换为 []byte
:
bytes := []byte(str)
但这不是一个数组,而是一个切片。此外,byte
!= rune
。如果您想对“字符”进行操作,您需要使用 rune
... 而不是 byte
。
除了上面提到的方法,你还可以做一个技巧
s := "hello"
b := *(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))
去玩:http://play.golang.org/p/xASsiSpQmC
你永远不应该使用这个:-)
[]byte
对象 - 当您尝试修改时它会严重失败p
,参见:play.golang.org/p/WHGl756ucj。在您的情况下,不确定为什么您更喜欢双重不安全而不是 b := []byte(s)
方法。
cap()
,这意味着它正在读入未知内存。为此,我认为您需要确保分配完整的 reflect.SliceHeader
大小并手动设置 cap
。像这样的东西:play.golang.org/p/fBK4dZM-qD
[]byte
而不是一组字节[20]byte
...不相信我吗?查看 Rob Pike 在 this thread 上的回答[]byte("one", "two")
?