На этом шаге рассмотрим некоторые особенности работы со строками в языке Go.
Строки в языке Go являются неизменяемыми последовательностями произвольных байтов. В большинстве случаев байты в строках представляют текст Юникода в кодировке UTF-8. Наличие поддержки Юникода означает, что строки в языке Go могут содержать текст на смеси любых языков, известных в мире, без ограничений, накладываемых кодовыми страницами.
Тип string в языке Go в корне отличается от эквивалентных типов во многих других языках. Тип String в языке Java, std::string в языке C++ и str – в Python 3 – все они являются последовательностями символов фиксированного размера (с некоторыми ограничениями), тогда как строки в языке Go являются последовательностями символов переменного размера, где каждый символ может быть представлен одним или более байтами, обычно в кодировке UTF-8.
На первый взгляд может показаться, что строки в других языках удобнее, чем строки в языке Go, потому что они позволяют обращаться к символам непосредственно, что в языке Go возможно, только если строка состоит исключительно из 7-битных символов ASCII (так как в кодировке UTF-8 каждый из них представлен единственным байтом). Однако с практической точки зрения подобное отличие не является проблемой для программистов на языке Go:
Хранение текста в кодировке UTF-8 имеет определенные преимущества, по сравнению со строками в языке Java или Python, каждый из которых также поддерживает строки Юникода. В языке Java строки представлены последовательностями кодовых пунктов, каждый из которых занимает 16 бит; в Python, в версиях с 2.x по 3.2, используется тот же подход, но в нем для хранения кодовых пунктов отводятся 16 или 32 бита, в зависимости от параметров сборки Python. Это означает, что для текста на английском языке в Go отводится по 8 бит на каждый символ, тогда как в Java и Python – как минимум в два раза больше. Еще одно преимущество заключается в том, что при использования кодировки UTF-8 аппаратный порядок следования байтов не имеет значения, тогда как при использовании кодировок UTF-16 и UTF-32 его необходимо учитывать (например, чтобы обеспечить корректное декодирование текста, может потребоваться использовать кодировку UTF-16 с обратным порядком следования байт). Кроме того, учитывая, что кодировка UTF-8 фактически стала стандартом кодирования текстовых файлов во всем мире, в других языках программирования приходится кодировать и декодировать такие файлы, чтобы обеспечить преобразование их содержимого во внутреннее представление Юникода и обратно, тогда как в Go можно непосредственно читать и записывать такие файлы. Помимо этого, некоторые крупные библиотеки (такие как GTK+) уже используют строки символов в кодировке UTF-8, поэтому программы на языке Go могут работать с ними, минуя этап кодирования/декодирования.
Фактически строки в языке Go удобны и просты в использовании, как и в других языках.
До появления Юникода было невозможно обеспечить сохранение в одном файле текста на разных языках, например включить в текст на английском языке цитаты на японском и русском языках, поскольку для разных языков использовались разные кодировки, и для каждого текстового файла могла использоваться только одна кодировка. Юникод обеспечивает возможность представления символов из всех известных систем письменности, поэтому один текстовый файл, для которого используется кодировка Юникод, может содержать текст на смеси самых разных языков, а также математические, полиграфические и другие специальные символы.
Каждый символ Юникода имеет уникальный идентификационный номер, называемый кодовым пунктом (code point). Всего определено более 100 000 символов Юникода с кодовыми пунктами в диапазоне от 0x0 до 0x10FFFF (последний определен в языке Go как константа unicode.MaxRune), с некоторыми промежутками и специальными областями. Согласно документации к Юникоду, кодовые пункты записываются четырьмя шестнадцатеричными цифрами в форме U+hhhh, например: U+21D4 – для символа '⇔'.
Отдельные кодовые пункты (то есть символы) в языке Go представлены значениями типа rune (синоним типа int32). Текст Юникода в файлах или в памяти должен быть представлен с применением некоторой кодировки. Стандарт Юникода определяет различные форматы преобразования Юникода (Unicode Transformation Formats), или кодировки, такие как UTF-8, UTF-16 и UTF-32. В языке Go для представления строк используется кодировка UTF-8.
UTF-8 – это наиболее широко используемая кодировка – она фактически является стандартом кодирования текстовых файлов и по умолчанию используется для файлов в форматах XML и JSON.
Для представления каждого кодового пункта в кодировке UTF-8 может использоваться от одного до четырех байт. Для строк, содержащих только 7-битные символы ASCII, байты и символы отображаются друг в друге непосредственно, потому что каждый 7-битный символ ASCII представлен в кодировке UTF-8 единственным байтом (с тем же значением). Как следствие текст на английском языке в кодировке UTF-8 хранится очень компактно (на каждый символ отводится единственный байт); как другое следствие – текстовый файл в 7-битной кодировке ASCII ничем не отличается от текстового файла с тем же текстом в кодировке UTF-8.
На следующем шаге рассмотрим литералы, операторы и экранированные последовательности в Go.