如何将字符串分配给字节数组

huangapple go评论68阅读模式
英文:

How to assign string to bytes array

问题

我想将字符串赋值给字节数组:

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

还有其他方法吗?

英文:

I want to assign string to bytes array:

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

Have another method?

答案1

得分: 730

安全且简单:

[]byte("这是一个字符串....")

英文:

Safe and simple:

[]byte("Here is a string....")

答案2

得分: 255

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

[]byte(str)

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

arr[:]

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

copy(arr[:], str)

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

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

  • 内置的copy函数只能将数据从切片复制到切片。
  • 数组是“底层数据”,而切片是“底层数据的视图”。
  • 使用[:]使数组符合切片的要求。
  • 字符串不能作为可以复制到的切片,但可以作为可以复制自的切片(字符串是不可变的)。
  • 如果字符串太长,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上提供了这段代码。

英文:

For converting from a string to a byte slice, string -> []byte:

[]byte(str)

For converting an array to a slice, [20]byte -> []byte:

arr[:]

For copying a string to an array, string -> [20]byte:

copy(arr[:], str)

Same as above, but explicitly converting the string to a slice first:

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

This code:

var arr [20]byte
copy(arr[:], "abc")
fmt.Printf("array: %v (%T)\n", arr, arr)

...gives the following output:

array: [97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] ([20]uint8)

I also made it available at the Go Playground

答案3

得分: 122

例如,

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]
英文:

For example,

package main

import "fmt"

func main() {
	s := "abc"
	var a [20]byte
	copy(a[:], s)
	fmt.Println("s:", []byte(s), "a:", a)
}

Output:

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]

答案4

得分: 45

arr := []byte("就这些了伙计们!!")

英文:

Piece of cake:

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

答案5

得分: 31

我认为这样更好..

package main

import "fmt"

func main() {
    str := "abc"
    mySlice := []byte(str)
    fmt.Printf("%v -> '%s'", mySlice, mySlice)
}

在这里查看:http://play.golang.org/p/vpnAWHZZk7

英文:

I think it's better..

package main

import "fmt"

func main() {
	str := "abc"
	mySlice := []byte(str)
	fmt.Printf("%v -> '%s'",mySlice,mySlice )
}

Check here: http://play.golang.org/p/vpnAWHZZk7

答案6

得分: 15

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, " ")

	// 字节数组值
	fmt.Println([]byte(stringByte))

	// 对应的字符串值
	fmt.Println(string([]byte(stringByte)))
}

输出:

[104 101 108 108 111 32 119 111 114 108 100] hello world

请查看链接playground

英文:

Go, convert a string to a bytes slice

You need a fast way to convert a []string to []byte type. To use in situations such as storing text data into a random access file or other type of data manipulation that requires the input data to be in []byte type.

package main

func main() {

    var s string

    //...

    b := []byte(s)

    //...
}

which is useful when using ioutil.WriteFile, which accepts a bytes slice as its data parameter:

WriteFile func(filename string, data []byte, perm os.FileMode) error

Another example

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

Output:

> [104 101 108 108 111 32 119 111 114 108 100] hello world

Please check the link playground

答案7

得分: 1

除了上面提到的方法,你还可以使用一个技巧:

s := "hello"
b := *(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))

Go Play: http://play.golang.org/p/xASsiSpQmC

你永远不应该使用这个方法 如何将字符串分配给字节数组

英文:

Besides the methods mentioned above, you can also do a trick as

s := "hello"
b := *(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))

Go Play: http://play.golang.org/p/xASsiSpQmC

You should never use this 如何将字符串分配给字节数组

答案8

得分: 1

Ended up creating array specific methods to do this. Much like the encoding/binary package with specific methods for each int type. For example 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)

Output:

[0 0 0 0 0 0 0 0 0 0 0 0 0 97 98 99]

Notice how I wanted padding on the left, not the right.

http://play.golang.org/p/7tNumnJaiN

英文:

Ended up creating array specific methods to do this. Much like the encoding/binary package with specific methods for each int type. For example 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)

Output:

[0 0 0 0 0 0 0 0 0 0 0 0 0 97 98 99]

Notice how I wanted padding on the left, not the right.

http://play.golang.org/p/7tNumnJaiN

答案9

得分: 1

数组是值...切片更像是指针。也就是说,[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的种类不是数组,而是切片,而[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

英文:

Arrays are values... slices are more like pointers. That is [n]type is not compatible with []type as they are fundamentally two different things. You can get a slice that points to an array by using arr[:] which returns a slice that has arr as it's backing storage.

One way to convert a slice of for example []byte to [20]byte is to actually allocate a [20]byte which you can do by using var [20]byte (as it's a value... no make needed) and then copy data into it:

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

Essentially what a lot of other answers get wrong is that []type is NOT an array.

[n]T and []T are completely different things!

When using reflect []T is not of kind Array but of kind Slice and [n]T is of kind Array.

You also can't use map[[]byte]T but you can use map[[n]byte]T.

This can sometimes be cumbersome because a lot of functions operate for example on []byte whereas some functions return [n]byte (most notably the hash functions in crypto/*).
A sha256 hash for example is [32]byte and not []byte so when beginners try to write it to a file for example:

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

they will get an error. The correct way of is to use

w.Write(sum[:])

However, what is it that you want? Just accessing the string bytewise? You can easily convert a string to []byte using:

bytes := []byte(str)

but this isn't an array, it's a slice. Also, byte != rune. In case you want to operate on "characters" you need to use rune... not byte.

答案10

得分: 0

如果有人想要快速进行切片之间的转换,可以参考以下比较。

package demo_test

import (
	"testing"
	"unsafe"
)

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

// 避免复制数据。
func UnsafeStrToBytes(s string) []byte {
	return *(*[]byte)(unsafe.Pointer(&s))
}

// 避免复制数据。
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
英文:

If someone is looking for a quick <sup>consider use unsafe</sup> conversion between slices, you can refer to the following comparison.

package demo_test

import (
	&quot;testing&quot;
	&quot;unsafe&quot;
)

var testStr = &quot;hello world&quot;
var testBytes = []byte(&quot;hello world&quot;)

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

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

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

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

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

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

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

output

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

huangapple
  • 本文由 发表于 2011年11月7日 10:29:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/8032170.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定