Відповіді:
Безпечний і простий:
[]byte("Here is a string....")
[]byte("one", "two")
?
Для перетворення з рядка в байтовий фрагмент 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
b[i] = []byte("A")[0]
працює, але в b[i] = 'A'
кінцевому підсумку набагато чистіший.
b[1] = '本'
Наприклад,
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
Функція `копіювання не є німою. Додавання та копіювання фрагментів : "Кількість скопійованих елементів - мінімум 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
Вам потрібен швидкий спосіб перетворити рядок [] в байт []. Використовувати в таких ситуаціях, як збереження текстових даних у файл випадкового доступу або інший тип маніпуляцій з даними, що вимагає введення даних у байтовому форматі [].
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] привіт, світ
Перевірте посилання на ігровий майданчик
Закінчилося створення специфічних методів для цього масиву. Так само, як кодування / бінарний пакет із конкретними методами для кожного типу 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]
Зверніть увагу, як я хотів прокладки зліва, а не справа.
byte16PutString
це свого роду повторне реалізація вбудованої copy
функції, яка підтримує лише створення нових масивів замість використання існуючих. copy
має спеціальну підтримку компілятора, тому він може обробляти різні типи аргументів, і він, ймовірно, має дійсно високопродуктивну реалізацію під обкладинками. Також питання ОП запитували про написання рядка до наявного масиву, а не про виділення нового, хоча більшість інших відповідей, здається, теж ігнорують це ...
answer
- це правильно, кожне тіло тут, щоб навчатись та заохочувати інших
Окрім згаданих вище методів, ви також можете зробити трюк як
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
Масиви - це значення ... фрагменти більше нагадують покажчики. Це є[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
не є з роду 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
то ви отримаєте помилку "індекс поза діапазоном".