Подтвердить что ты не робот

Насколько дорогим является [] байт (строка)?

Преобразуйте string в []byte:

func toBytes(s string) []byte {
  return []byte(s) // What happens here?
}

Насколько велика эта операция литья? Выполняется ли копирование? Насколько я вижу в спецификации Go: Строки ведут себя как кусочки байтов, но неизменяемы, это должно включать, по крайней мере, копирование, чтобы убедиться, что последующие операции среза не изменят нашу строку s. Что происходит с обратным разговором? Разве разговор []byte <-> string включает кодирование/декодирование, например utf8 ↔ runes?

4b9b3361

Ответ 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. Это не обескураживает и не нарушает никаких намерений. Он просто выполняет итерацию по строковой байт-мудре, что иногда просто то, что вы хотите сделать.