Насколько дорогим является [] байт (строка)?
Преобразуйте string
в []byte
:
func toBytes(s string) []byte {
return []byte(s) // What happens here?
}
Насколько велика эта операция литья? Выполняется ли копирование? Насколько я вижу в спецификации Go: Строки ведут себя как кусочки байтов, но неизменяемы, это должно включать, по крайней мере, копирование, чтобы убедиться, что последующие операции среза не изменят нашу строку s
. Что происходит с обратным разговором? Разве разговор []byte <-> string
включает кодирование/декодирование, например utf8 ↔ runes?
Ответы
Ответ 1
[]byte(s)
- это не актерский, а conversion. Некоторые преобразования такие же, как и приведение, например uint(myIntvar)
, которое просто переинтерпретирует бит на месте. К сожалению, это не случай преобразования строки в байтовый бит. Байтовые фрагменты являются изменяемыми, строки (строковые значения, если быть точными) не являются. Результатом является необходимая копия (mem alloc + content transfer) строки, создаваемой. Так что да, это может быть дорогостоящим в некоторых сценариях.
EDIT: преобразование кодирования не выполняется. Строковые (исходные) байты копируются в байты среза (назначения), как они есть.
Ответ 2
Преобразование копирует байты, но также выделяет пространство для [] байта в куче. В случаях, когда вы последовательно конвертируете строки в [], вы можете сэкономить время управления памятью, повторно используя [] байт и используя команду копирования. (См. http://golang.org/ref/spec#Appending_and_copying_slices и специальный случай об использовании строки в качестве источника.)
В обоих случаях преобразования и команды копирования сама копия является прямой копией байта, которая должна выполняться очень быстро. Я бы ожидал, что компилятор сгенерирует какую-то команду повторного перемещения, которая эффективно выполняет процессор.
Обратное преобразование, создающее строку из байтового фрагмента, обязательно включает выделение строки в куче. Свойство непреложности вынуждает это. Иногда вы можете оптимизировать, выполняя как можно большую работу с [] байт, а затем создавая строку в конце. Часто используется байты типа Buffer.
В погоне за красной селедкой, кодирование и UTF-8 не являются проблемами. Строки и [] байт могут содержать произвольные данные. Копия не смотрит на данные, она просто копирует их. Правильно выбирайте слова, когда говорите, что строки, подобные строкам, должны содержать UTF-8 или что это рекомендуется. Более точно просто отметить, что некоторые языковые функции, такие как предложение диапазона оператора for, интерпретируют строки как UTF-8. Просто узнайте, что интерпретирует строки как UTF-8, а что нет. Имейте не-UTF-8 в строке и нужно перебирать по нему байты? Нет проблем, просто не используйте предложение диапазона.
s := "string"
for i := 0; i < len(s); i++ {
b := s[i]
// work with b
}
Это идиоматический Go. Это не обескураживает и не нарушает никаких намерений. Он просто выполняет итерацию по строковой байт-мудре, что иногда просто то, что вы хотите сделать.