Golang: Строки
В Go строки представлены типом string
. Это неизменяемая последовательность байт, закодированных в UTF-8. Строки — один из самых часто используемых типов данных, особенно при работе с текстами, запросами, HTTP и файловыми путями.
Строки можно объявлять двумя способами
var name string = "Hexlet"
// Сокращённая форма через вывод типа
greeting := "Hello"
Обычные строки записываются в двойных кавычках. Но если строка многострочная или содержит спецсимволы (например, \n или кавычки), её удобнее оформлять в сырых литералах — через обратные кавычки:
sql := `
SELECT *
FROM users
WHERE active = true
`
В таких строках сохраняются все отступы, переносы и символы как есть, без экранирования.
Конкатенация
Объединить строки можно с помощью оператора +
:
"hello " + "world" // "hello world"
Go поддерживает сокращенный синтаксис конкатенации строк если используются переменные:
text := "Hello"
text += " World"
fmt.Println(text) // Hello World
Конкатенация возможна только между значениями типа string. Смешивание типов приведёт к ошибке компиляции:
name := "Hexlet"
age := 10
// name + age // ошибка: mismatched types string and int
Преобразование чисел в строки
В Go числа не конвертируются в строки автоматически. Более того, выражение string(number)
не преобразует число в его текстовое представление. Вместо этого число рассматривается как код Unicode, и результатом будет символ с этим кодом.
Например:
fmt.Println(string(65)) // "A", так как 65 — код символа 'A'
fmt.Println(string(49)) // "1", так как 49 — код символа '1'
fmt.Println(string(5)) // непечатаемый символ
Чтобы получить строку с текстовым значением числа, нужно использовать пакет strconv
:
import "strconv"
count := 5
msg := "You have " + strconv.Itoa(count) + " new messages"
fmt.Println(msg) // "You have 5 new messages"
Для чисел с плавающей точкой применяется strconv.FormatFloat
, например:
pi := 3.14
msg := "Pi is approximately " + strconv.FormatFloat(pi, 'f', 2, 64)
fmt.Println(msg) // "Pi is approximately 3.14"
Форматирование строк
Go не поддерживает интерполяцию строк напрямую. Вместо этого используется функция fmt.Sprintf()
, которая работает по шаблону:
import "fmt"
name := "Hexlet"
msg := fmt.Sprintf("Hello, %s!", name) // "Hello, Hexlet!"
Длина строки
Для определения длины строки используется встроенная функция len()
:
len("hexlet") // 6
Строки в Go — это последовательности байт, а не символов. Это важно, потому что один символ в UTF-8 (например, кириллический или emoji) может занимать 2, 3 или 4 байта. Например:
len("го") // 4 (по 2 байта на символ)
len("😀") // 4
len("hello") // 5
Чтобы корректно работать с символами, а не байтами, в Go есть специальный тип — rune
. rune
— это псевдоним для int32
, который обозначает один юникод-символ. Поэтому если мы хотим посчитать количество символов, а не байт, то нам придется воспользоваться функцией utf8.RuneCountInString()
.
import "unicode/utf8"
utf8.RuneCountInString("хекслет") // 6
Обращение к символам
Строка в Go — это массив байт. Поэтому при обращении по индексу (s[i]
) возвращается байт, а не символ:
s := "Привет"
// первый байт
fmt.Println(s[0]) // => 208
// некорректный символ
fmt.Printf("%c\n", s[0]) // => Ð
Чтобы получить символ, нужно преобразовать строку в срез (динамический массив) рун. Массивы и срез проходятся чуть дальше, но код имеет смысл посмотреть уже сейчас.
runes := []rune("Привет")
// код точки Unicode
fmt.Println(runes[0]) // => 1055
fmt.Printf("%c\n", runes[0]) // => П
Задание
В рамках обучения вы разрабатываете командную утилиту, которая выводит приветствие пользователю и включает в себя информацию о количестве новых сообщений. Реализуйте функцию BuildGreeting()
, которая принимает два аргумента:
name
(типstring
) — имя пользователяcount
(типint
) — количество новых сообщений
Функция должна возвращать строку в следующем формате:
Hello, <имя>! You have <число> new messages.
Примеры
BuildGreeting("Ivan", 5) // "Hello, Ivan! You have 5 new messages."
BuildGreeting("Hexlet", 0) // "Hello, Hexlet! You have 0 new messages."
Полезное
Команда проекта находится в телеграм-сообществе. Там можно задать любой вопрос и повлиять на проект
Если вы зашли в тупик, то самое время поговорить с нашим асситентом Тота во вкладке "ИИ-помощник":
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи. В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в обратной связи нашего сообщества
Ваше упражнение проверяется по этим тестам
package solution
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestBuildGreeting(t *testing.T) {
a := assert.New(t)
a.Equal("Hello, Ivan! You have 5 new messages.", BuildGreeting("Ivan", 5))
a.Equal("Hello, Hexlet! You have 0 new messages.", BuildGreeting("Hexlet", 0))
a.Equal("Hello, Anna! You have 3 new messages.", BuildGreeting("Anna", 3))
a.Equal("Hello, GoUser! You have 100 new messages.", BuildGreeting("GoUser", 100))
}
Решение учителя откроется через:
20:00
