Лучшие практики кодирования в Go - это использование байта, []byteа не набора байтов [20]byteпри преобразовании строки в байты ... Не верьте мне? Проверьте ответ Роба Пайка на эту тему
openwonk
9
ОП спросил о массиве, а не о срезе. В некоторых случаях вам нужно ограничить размер среза и использовать вместо него массив. Мой ответ ниже обрезает дополнительные символы, чтобы вы не переполняли массив.
DavidG
3
Для тех, кто считает, что это выглядит немного странно: это просто преобразование типов в Go: golang.org/ref/spec#Conversions
Cnly
Любой способ добавить несколько строк и объединить их? например []byte("one", "two")?
Раким
К сожалению, нет, @rakim, вы можете передать только одну строку ... так что вы должны сначала объединить их или объединить несколько кусков байтов (за рамками этого вопроса).
openwonk
149
Для преобразования строки в фрагмент байта 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)
Возможно, вы захотите добавить пример для преобразования одного символа. Я сделал вывод, что это b[i] = []byte("A")[0]работает, но в b[i] = 'A'итоге получается намного чище.
Алекс Янсен
1
Это не работает для многобайтовых рун:b[1] = '本'
Александр
110
Например,
package main
import"fmt"
func main(){
s :="abc"var a [20]byte
copy(a[:], s)
fmt.Println("s:",[]byte(s),"a:", a)}
Это единственный ответ, который фактически касается исходного вопроса.
Джек О'Коннор
Зачем назначать 20 байтов, а не конкретные, которые вам действительно нужны для строки? Если строке нужно меньше 20, не слишком ли это малоэффективно? И также подвержен ошибкам, если он превышает 20?
Сэр
1
@Sir: Мы не назначаем 20 байтов. Мы копируем 3 байта, длина s, функция `copy не глупа. Добавление и копирование фрагментов : «Количество скопированных элементов - это минимум len (src) и len (dst)».
Это, кажется, не отвечает на вопрос. OP хотел записать байты строки в существующий массив, который может быть длиннее строки.
Джек О'Коннор
2
Использование срезов []byteпредпочтительнее массивов [20]byte. Ответ правильный на основе лучших практик; если для спецификаций или кода требуются массивы, используйте copyвместо этого (см. примеры в другом месте в этой теме).
Это не лучше Это не правильно. Это не делает то, что задал вопрос.
peterSO
10
Go, преобразовать строку в байтовый срез
Вам нужен быстрый способ преобразования строки [] в тип байта []. Для использования в ситуациях, таких как сохранение текстовых данных в файле произвольного доступа или другого типа манипулирования данными, который требует, чтобы входные данные имели тип байта [].
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)))}
Закончилось создание специальных методов для этого. Очень похоже на кодировку / двоичный пакет с конкретными методами для каждого типа int. Например binary.BigEndian.PutUint16([]byte, uint16).
func byte16PutString(s string)[16]byte{var a [16]byteif 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)
Вывод:
[0000000000000979899]
Обратите внимание, как я хотел заполнить слева, а не справа.
Если вы не голосуете за ответ, оставьте комментарий, почему вы находите решение не оптимальным или как оно не относится к вопросу ОП.
DavidG
3
Я думаю, что отрицательные отзывы byte16PutString- это своего рода переопределение встроенной copyфункции, которая поддерживает создание только новых массивов, а не использование существующих. copyимеет специальную поддержку компилятора, поэтому он может обрабатывать различные типы аргументов и, вероятно, имеет действительно высокопроизводительную реализацию под прикрытием. Кроме того, вопрос ОП задал вопрос о записи строки в существующий массив, а не о выделении нового, хотя большинство других ответов, похоже, тоже игнорируют это ...
Джек О'Коннор
Спасибо @ JackO'Connor Я тоже здесь за обучение и ценю конструктивную обратную связь, а не просто откровенное голосование.
DavidG
не знаю, почему его голос «за» answer- это правильно, все здесь, чтобы учиться и ободрять других
muthukumar helius
-1
Помимо методов, упомянутых выше, вы также можете сделать трюк, как
s :="hello"
b :=*(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))
Это безумие. Я думаю, что стоит добавить «но вы не должны» в конце вашего ответа. Помимо того, что на самом деле он не отвечает на этот вопрос (OP говорит о байтовом массиве, а не о срезах), вы, похоже, не получаете []byteнужный объект, используя свое «преобразование» - он плохо работает, когда вы пытаетесь внести изменения p, см .: play.golang.org/p/WHGl756ucj . В вашем случае не уверен, почему вы предпочитаете двойной небезопасный b := []byte(s)метод.
Томас
1
@tomasz Я не предпочитаю делать байты строки <-> [] таким образом, просто показываю другую опцию :-) и да, вы правы, я неправильно понял вопрос.
Брэндон Гао
Когда я делаю это, результат имеет cap()произвольный размер, что означает, что он читает в неизвестную память. Чтобы это было правильно, я думаю, вам нужно убедиться, что вы выделите полный reflect.SliceHeaderразмер и вручную установите cap. Примерно так: play.golang.org/p/fBK4dZM-qD
Массивы - это значения ... срезы больше похожи на указатели. Это [n]typeнесовместимо с тем, []typeчто это принципиально две разные вещи. Вы можете получить фрагмент, который указывает на массив, используя arr[:]который возвращает фрагмент, который имеет в arrкачестве резервного хранилища.
Например, один из способов преобразования фрагмента []byteв [20]byte- это фактически выделить то, [20]byteчто вы можете сделать, используя var [20]byte(так как это значение ... не makeнужно), а затем скопировать в него данные:
По сути, многие другие ответы не так, что []typeэто не массив.
[n]Tи []Tэто совершенно разные вещи!
При использовании отражение []Tимеет вид не Array, а типа Slice и [n]Tимеет вид Array.
Вы также не можете использовать, 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.
str
больше, чем длина,arr
вы получите ошибку «индекс вне диапазона».Ответы:
Безопасно и просто:
источник
[]byte
а не набора байтов[20]byte
при преобразовании строки в байты ... Не верьте мне? Проверьте ответ Роба Пайка на эту тему[]byte("one", "two")
?Для преобразования строки в фрагмент байта
string -> []byte
:Для преобразования массива в срез
[20]byte -> []byte
:Для копирования строки в массив
string -> [20]byte
:То же, что и выше, но сначала явно преобразуем строку в фрагмент:
copy
функция копирует только в срез, из среза.[:]
делает массив квалифицированным как срез.copy
будет скопирована только та часть строки, которая подходит.Этот код:
... дает следующий вывод:
Я также сделал его доступным на Go Playground
источник
b[i] = []byte("A")[0]
работает, но вb[i] = 'A'
итоге получается намного чище.b[1] = '本'
Например,
Вывод:
источник
s
, функция `copy не глупа. Добавление и копирование фрагментов : «Количество скопированных элементов - это минимум len (src) и len (dst)».Кусок пирога:
источник
[]byte
предпочтительнее массивов[20]byte
. Ответ правильный на основе лучших практик; если для спецификаций или кода требуются массивы, используйтеcopy
вместо этого (см. примеры в другом месте в этой теме).Я думаю, что это лучше ..
Проверьте здесь: http://play.golang.org/p/vpnAWHZZk7
источник
Go, преобразовать строку в байтовый срез
Вам нужен быстрый способ преобразования строки [] в тип байта []. Для использования в ситуациях, таких как сохранение текстовых данных в файле произвольного доступа или другого типа манипулирования данными, который требует, чтобы входные данные имели тип байта [].
что полезно при использовании ioutil.WriteFile, который принимает срез байтов в качестве параметра данных:
Другой пример
Вывод:
Пожалуйста, проверьте ссылку игровая площадка
источник
Закончилось создание специальных методов для этого. Очень похоже на кодировку / двоичный пакет с конкретными методами для каждого типа int. Например
binary.BigEndian.PutUint16([]byte, uint16)
.Вывод:
Обратите внимание, как я хотел заполнить слева, а не справа.
http://play.golang.org/p/7tNumnJaiN
источник
byte16PutString
- это своего рода переопределение встроеннойcopy
функции, которая поддерживает создание только новых массивов, а не использование существующих.copy
имеет специальную поддержку компилятора, поэтому он может обрабатывать различные типы аргументов и, вероятно, имеет действительно высокопроизводительную реализацию под прикрытием. Кроме того, вопрос ОП задал вопрос о записи строки в существующий массив, а не о выделении нового, хотя большинство других ответов, похоже, тоже игнорируют это ...answer
- это правильно, все здесь, чтобы учиться и ободрять другихПомимо методов, упомянутых выше, вы также можете сделать трюк, как
Go Play: 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Массивы - это значения ... срезы больше похожи на указатели. Это
[n]type
несовместимо с тем,[]type
что это принципиально две разные вещи. Вы можете получить фрагмент, который указывает на массив, используяarr[:]
который возвращает фрагмент, который имеет вarr
качестве резервного хранилища.Например, один из способов преобразования фрагмента
[]byte
в[20]byte
- это фактически выделить то,[20]byte
что вы можете сделать, используяvar [20]byte
(так как это значение ... неmake
нужно), а затем скопировать в него данные:По сути, многие другие ответы не так, что
[]type
это не массив.[n]T
и[]T
это совершенно разные вещи!При использовании отражение
[]T
имеет вид не Array, а типа Slice и[n]T
имеет вид Array.Вы также не можете использовать,
map[[]byte]T
но вы можете использоватьmap[[n]byte]T
.Иногда это может быть громоздким, потому что многие функции работают, например, в
[]byte
то время как некоторые функции возвращают[n]byte
(особенно хеш-функции вcrypto/*
). Например, хэш sha256 - это[32]byte
не[]byte
так, когда новички пытаются записать его в файл, например:они получат ошибку. Правильный способ заключается в использовании
Однако что вы хотите? Просто доступ к строке байтово? Вы можете легко преобразовать
string
в[]byte
использование:но это не массив, это кусочек. Также
byte
! =rune
. Если вы хотите оперировать «персонажами», вам нужно использоватьrune
... нетbyte
.источник