Как присвоить строку массиву байтов
Заголовок: Как преобразовать строку в массив байт в Go?
Текст проблемы:
Я хочу назначить строку массиву байт в Go. У меня есть следующий код:
var arr [20]byte
str := "abc"
for k, v := range []byte(str) {
arr[k] = byte(v)
}
Однако я ищу другой способ сделать это более эффективно или элегантно. Есть ли альтернативные методы для преобразования строки в массив байт?
5 ответ(ов)
Чтобы перевести строку в срез байтов в языке Go, вы можете использовать следующий простой и безопасный способ:
data := []byte("Here is a string....")
Этот код создает срез байтов data
, который содержит байты, представляющие строку "Here is a string....". Такой подход обеспечивает конвертацию строки в срез байтов без дополнительных сложностей.
Ваш код на Go показывает, как скопировать строку в массив байтов. Давайте разберем его шаг за шагом.
package main
import "fmt"
func main() {
s := "abc"
var a [20]byte
copy(a[:], s)
fmt.Println("s:", []byte(s), "a:", a)
}
Вы сначала определяете строку s
с значением "abc"
. Затем вы создаете массив a
из 20 байтов. Функция copy
используется для копирования содержимого строки s
в массив a
. Важно отметить, что при преобразовании строки в байты, каждый символ в строке представляется в кодировке UTF-8, что соответствует их ASCII-кодам. В данном случае:
'a'
соответствует 97,'b'
соответствует 98,'c'
соответствует 99.
Вывод программы:
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]
Как видно из вывода, ваша строка преобразуется в массив байтов [97 98 99]
, а в массиве a
находятся эти же значения, после которых идут нули, так как массив a
был инициализирован с нулевыми значениями по умолчанию.
Это поведение объясняется тем, что массив a
имеет фиксированный размер 20 байтов. Когда выполняется копирование, в массив a
помещаются только первые три байта (т.е. значения символов a
, b
и c
), а остальные места остаются нулевыми.
Конечно! Если вы хотите создать массив байтов в Go с использованием строки "That's all folks!!", вы можете сделать это следующим образом:
arr := []byte("That's all folks!!")
В этом коде arr
будет представлять собой срез байтов, который содержит данные из строки. Использование []byte()
преобразует строку в массив байтов, что может быть полезно, например, для работы с бинарными данными или при необходимости модификации отдельных байтов в строке.
Ваш код в целом корректен, но есть один нюанс, который следует учесть. Когда вы создаете срез байтов mySlice
из строки str
, и затем выводите его с помощью fmt.Printf
, результат будет отображаться как массив байтов, а не как строка. Чтобы получить корректный вывод строки, вам следует использовать %s
для отображения mySlice
. Вот исправленный пример:
package main
import "fmt"
func main() {
str := "abc"
mySlice := []byte(str)
fmt.Printf("%v -> '%s'\n", mySlice, string(mySlice))
}
В этом варианте мы оборачиваем mySlice
в string(mySlice)
, чтобы корректно отобразить его как строку. Теперь вывод будет выглядеть как abc -> 'abc'
. Вы можете протестировать код по приведенной вами ссылке: http://play.golang.org/p/vpnAWHZZk7.
Если вы ищете быстрый способ выполнить конвертацию между срезами с использованием unsafe
, обратите внимание на следующее сравнение.
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
Как видно из результатов, методы UnsafeStrToBytes
и UnsafeBytesToStr
обеспечивают значительно более высокую производительность по сравнению с их безопасными аналогами, избегая при этом лишнего копирования данных. Однако стоит помнить, что использование unsafe
может привести к неопределенному поведению, если не соблюдать осторожность.
Существует ли цикл foreach в Go?
Как сопоставить любой символ на нескольких строках в регулярном выражении?
Отформатировать строку в Go без вывода?
Какой идиоматичный эквивалент тернарного оператора C в Go?
Есть ли способ получить доступ к приватным полям структуры из другого пакета?