我想把字符串赋值给bytes数组:

var arr [20]byte
str := "abc"
for k, v := range []byte(str) {
  arr[k] = byte(v)
}

还有别的方法吗?


当前回答

如果有人正在寻找一个快速考虑使用不安全转换片之间,可以参考下面的比较。

package demo_test

import (
    "testing"
    "unsafe"
)

var testStr = "hello world"
var testBytes = []byte("hello world")

// Avoid copying the data.
func UnsafeStrToBytes(s string) []byte {
    return *(*[]byte)(unsafe.Pointer(&s))
}

// Avoid copying the data.
func UnsafeBytesToStr(b []byte) string {
    return *(*string)(unsafe.Pointer(&b))
}

func Benchmark_UnsafeStrToBytes(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = UnsafeStrToBytes(testStr)
    }
}

func Benchmark_SafeStrToBytes(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = []byte(testStr)
    }
}

func Benchmark_UnSafeBytesToStr(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = UnsafeBytesToStr(testBytes)
    }
}

func Benchmark_SafeBytesToStr(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = string(testBytes)
    }
}

go test -v -bench="^Benchmark" -run=none

输出

cpu: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz
Benchmark_UnsafeStrToBytes
Benchmark_UnsafeStrToBytes-8    1000000000               0.2465 ns/op
Benchmark_SafeStrToBytes
Benchmark_SafeStrToBytes-8      289119562                4.181 ns/op
Benchmark_UnSafeBytesToStr
Benchmark_UnSafeBytesToStr-8    1000000000               0.2530 ns/op
Benchmark_SafeBytesToStr
Benchmark_SafeBytesToStr-8      342842938                3.623 ns/op
PASS

其他回答

如果有人正在寻找一个快速考虑使用不安全转换片之间,可以参考下面的比较。

package demo_test

import (
    "testing"
    "unsafe"
)

var testStr = "hello world"
var testBytes = []byte("hello world")

// Avoid copying the data.
func UnsafeStrToBytes(s string) []byte {
    return *(*[]byte)(unsafe.Pointer(&s))
}

// Avoid copying the data.
func UnsafeBytesToStr(b []byte) string {
    return *(*string)(unsafe.Pointer(&b))
}

func Benchmark_UnsafeStrToBytes(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = UnsafeStrToBytes(testStr)
    }
}

func Benchmark_SafeStrToBytes(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = []byte(testStr)
    }
}

func Benchmark_UnSafeBytesToStr(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = UnsafeBytesToStr(testBytes)
    }
}

func Benchmark_SafeBytesToStr(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = string(testBytes)
    }
}

go test -v -bench="^Benchmark" -run=none

输出

cpu: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz
Benchmark_UnsafeStrToBytes
Benchmark_UnsafeStrToBytes-8    1000000000               0.2465 ns/op
Benchmark_SafeStrToBytes
Benchmark_SafeStrToBytes-8      289119562                4.181 ns/op
Benchmark_UnSafeBytesToStr
Benchmark_UnSafeBytesToStr-8    1000000000               0.2530 ns/op
Benchmark_SafeBytesToStr
Benchmark_SafeBytesToStr-8      342842938                3.623 ns/op
PASS

将字符串转换为字节片

您需要一种快速的方法将[]字符串转换为[]字节类型。用于将文本数据存储到随机访问文件或要求输入数据为[]字节类型的其他类型的数据操作等情况。

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)))
}

输出:

你好,世界

请检查链接操场

数组是值…切片更像指针。也就是说[n]类型与[]类型不兼容,因为它们本质上是两种不同的东西。你可以通过使用arr[:]来获取一个指向数组的切片,它返回一个有arr作为后台存储的切片。

将例如[]字节的切片转换为[20]字节的一种方法是实际分配一个[20]字节,您可以使用var [20]byte(因为它是一个值…不需要make),然后复制数据到它:

buf := make([]byte, 10)
var arr [10]byte
copy(arr[:], buf)

从本质上讲,很多其他答案都是错误的,即[]类型不是一个数组。

[n]T和[]T是完全不同的东西!

当使用reflect时,[]T不是数组而是Slice,而[n]T是数组。

你也不能使用map[[]byte]T,但是你可以使用map[[n]byte]T。

这有时会很麻烦,因为很多函数都在[]字节上操作,而一些函数返回[n]字节(最明显的是crypto/*中的哈希函数)。 例如,sha256哈希是[32]字节而不是[]字节,所以当初学者尝试将其写入文件时,例如:

sum := sha256.Sum256(data)
w.Write(sum)

他们会得到一个错误。正确的方法是使用

w.Write(sum[:])

但是,你到底想要什么?只是按字节访问字符串?您可以使用以下方法轻松地将字符串转换为[]字节:

bytes := []byte(str)

但这不是数组,而是切片。另外,byte != rune。如果你想操作“字符”,你需要使用符文…不是字节。

string -> []byte用于将字符串转换为字节切片:

[]byte(str)

将数组转换为切片,使用[20]byte -> []byte:

arr[:]

将字符串复制到数组,使用string -> [20]byte:

copy(arr[:], str)

与上面相同,但首先显式地将字符串转换为slice:

copy(arr[:], []byte(str))

The built-in copy function only copies to a slice, from a slice. Arrays are "the underlying data", while slices are "a viewport into underlying data". Using [:] makes an array qualify as a slice. A string does not qualify as a slice that can be copied to, but it qualifies as a slice that can be copied from (strings are immutable). If the string is too long, copy will only copy the part of the string that fits (and multi-byte runes may then be copied only partly, which will corrupt the last rune of the resulting string).


这段代码:

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)

我还在围棋游乐场提供了它

小菜一碟:

arr := []byte("That's all folks!!")