Строки в GO: знакомство и начало работы

    Команда Simple-Server
    03.06.2026
    11 мин

    Материал подготовлен командой Simple-Server для администраторов VPS и выделенных серверов. Команды и пути проверяйте на тестовой машине перед production.

    Кратко о задаче

    Прежде всего стоит сказать, что в Golang строки устроены несколько иначе, чем в Java, C++ или Python. По сути, это последовательность символов, каждый из которых имеет разный размер — то есть он может быть представлен одним или несколькими байтами в кодировке UTF-8.

    Дело в том, что во времена изобретения языка C, символ в компьютере представлялся 7-битным кодом ASCII. Таким образом, строка представляла собой набор множества 7-битных символов ASCII.

    Однако по мере роста использования компьютеров во всем мире 7-битной схемы ASCII стало недостаточно для поддержки символов других языков. Поэтому были предложены различные модели кодировки символов, такие как Unicode, UTF-8, UTF-16, UTF-32 и т. д.

    Различные языки программирования имеют свою собственную схему кодировки символов. Например, Java изначально использует UTF-16. А вот Go, напротив, построен на кодировке UTF-8.

    Именно благодаря ей строка Go может содержать универсальный текст, представляющий собой смесь любого существующего в мире языка — без какой-либо путаницы или любых других ограничений. При этом сами строки всегда статичны и имеют неизменный состав.

    Существует несколько распространенных способов объявления (определения) строк в Go:

    // явное определение через «var» var variable1 = "some text" // явное определение через «var» с указанием типа, но без значения var variable2 string = "peace" // более короткое определение variable3 := "some text"

    Строку можно также объявить без явного указания значения. В этом случае строковая переменная инициализируется нулевым значением — пустой строкой:

    При использовании двойных кавычек при создании строковой переменной Go будет интерпретировать специальные (экранированные) символы, написанные через слэш. Например, такие как /n:

    import "fmt" ... var some_variable = "first line/nsecond line/nthird line" fmt.Println(some_variable) // выводим строку в консоль // ВЫВОД: // first line // second line // third line

    Для того, чтобы компилятор Go игнорировал спецсимволы и при этом сохранял оригинальное форматирование строк, нужно использовать одинарные (обратные) кавычки.

    Вот пример объявления Golang строки с явным указанием форматирования:

    import "fmt" ...  // переносы строк в переменной указывается явно без добавления спец символов var some_variable = `first line second line third line` fmt.Println(some_variable) // выводим строку в консоль // ВЫВОД: // first line // second line // third line

    Обратите внимание, что для вывода строк в консоль используется пакет fmt.

    А в этом примере Go полностью игнорирует экранированные символы:

    import "fmt" ... var some_variable = `upper line /n lower line` fmt.Println(some_variable) // выводим строку в консоль // ВЫВОД: upper line /n lower line

    Смысл существования специального типа String в том, чтобы работать не с «сырой» последовательностью байтов, а со специальными методами, управляющими ей.

    Однако, строго говоря, в Golang (в отличие от C и C++) строки изменять нельзя. Они статичны. Можно только получать доступ к конкретным символам по индексу:

    import "fmt" ... variable := "hello" c := variable[0] fmt.Printf("%c\n", c) // ВЫВОД: h

    Тем не менее, есть большое количество способов создания новых строк из уже существующих.

    Важно знать, что некоторые функции для преобразования строк требуют включения специального пакета strings:

    Конкатенация строк Golang

    Самая базовая манипуляция — соединение (конкатенация) нескольких строк в одну целую. Выполняется с помощью оператора сложения:

    import "fmt" ... var variable1 = "hello" var variable2 = "world" var space = " " var variable3 = variable1 + space + variable2 fmt.Println(variable3) // ВЫВОД: hello world fmt.Println(variable2 + ", " + variable1) // ВЫВОД: world, hello

    Обратите внимание, что вы не можете складывать строки с другими типами. Например, с числовыми:

    fmt.Println("i am " + 24 + " years old") // ОШИБКА

    Чтобы пример выше работал, необходимо использовать функцию преобразования типов. В данном случае из int в string:

    import "fmt" ... age := 24 fmt.Println("i am " +  strconv.Itoa(age) + " years old") // ВЫВОД: i am 24 years old fmt.Println("i am " +  strconv.Itoa(24) + " years old") // ВЫВОД: i am 24 years old

    Можно обрезать начальные и конечные символы строки, указав их в отдельном аргументе:

    import ( "fmt" "strings" ) ... result := strings.Trim("xxxhello worldxxx", "xxx") fmt.Println(result) // ВЫВОД: hello world

    Можно также разбить строку на подстроки, указав разделитель:

    import ( "fmt" "strings" ) ... result := strings.Split("hello world", " ") fmt.Println(result) // ВЫВОД: [hello world]

    Можно склеить несколько строк, размещенных в массиве, в одну целую строку, явно указав разделитель:

    import ( "fmt" "strings" ) ... result := strings.Join([]string{"hello", "world"}, " ") // в качестве аргумента указывается массив строк fmt.Println(result) // ВЫВОД: hello world

    Тем не менее, использование функции склеивания или оператора сложения для конкатенации строк — не самое лучшее решение. Такой род операций каждый раз создает новую строку, снижая производительность.

    Поэтому в Golang есть специальный оптимизированный инструмент для сбора целых строк из составных частей с указанием неких правил — Builder:

    import ( "fmt" "strings" ) ... builded := &strings.Builder{} builded.WriteString("very") builded.WriteString(" ") builded.WriteString("long") builded.WriteString(" ") builded.WriteString("line") fmt.Println(builded.String()) // ВЫВОД: very long line

    Более подробно об этом типе можно узнать в официальной документации Go. Тем не менее, использование Builder довольно тривиально, т.к. он не содержит большого числа методов.

    Разделить строку, указав отдельным аргументом разделитель, можно следующим образом:

    import ( "fmt" "strings" ) ... result := strings.Split("h-e-l-l-o", "-") fmt.Println(result) // ВЫВОД: [h e l l o]

    Также есть несколько вариантов замены определенной подстроки на другую подстроку:

    import ( "fmt" "strings" ) ... result := strings.Replace("hello", "l", "|", 1) // заменяем первое вхождение fmt.Println(result) // ВЫВОД: he|lo result = strings.Replace("hello", "l", "|", -1) // заменяем все вхождения fmt.Println(result) // ВЫВОД: he||o

    Go предоставляет возможность переключать регистр строк — увеличивать или уменьшать символы:

    import ( "fmt" "strings" ) ... result := strings.Replace("hello", "l", "|", 1) // заменяем первое вхождение fmt.Println(result) // ВЫВОД: he|lo result = strings.Replace("hello", "l", "|", -1) // заменяем все вхождения fmt.Println(result) // ВЫВОД: he||o

    Создание строки из последовательности байтов

    Вы также можете превратить последовательность явно указанных байтов в полноценную строку и работать уже с ней:

    import "fmt" ... // последовательность байтов any_bytes := []byte{0x47, 0x65, 0x65, 0x6b, 0x73} // создаем строку any_string := string(myslice1) fmt.Println(any_string) // ВЫВОД: Geeks

    Один из вариантов — проверить наличие некоторой подстроки в строке:

    import ( "fmt" "strings" ) ... result := strings.Contains("world", "rl") fmt.Println(result) // ВЫВОД: true result := strings.Contains("world", "rrl") fmt.Println(result) // ВЫВОД: false

    Разумеется, классические операторы сравнения тоже приспособлены для поиска совпадений. Каждый из них посимвольно сравнивает строки в их лексическом порядке и с учетом длины:

    import "fmt" ... fmt.Println("hello" == "hello") // ВЫВОД: true fmt.Println("hello" == "hello world") // ВЫВОД: false fmt.Println("hello" > "hell") // ВЫВОД: true fmt.Println("hello" > "lo") // ВЫВОД: false

    Наличие префикса и суффикса

    Помимо проверки на наличия подстроки, можно проверить вхождение в строку определенного префикса или суффикса:

    import ( "fmt" "strings" ) ... result := strings.HasPrefix("hello", "he") fmt.Println(result) // ВЫВОД: true result = strings.HasSuffix("hello", "lo") fmt.Println(result) // ВЫВОД: true result = strings.HasPrefix("hello", "el") fmt.Println(result) // ВЫВОД: false

    Индекс вхождения подстроки

    Можно получить индекс первого вхождения указанной подстроки:

    import ( "fmt" "strings" ) ... result := strings.Index("hello", "el") fmt.Println(result) // ВЫВОД: 1 result = strings.Index("hello", "le") fmt.Println(result) // ВЫВОД: -1

    Часто может потребоваться узнать длину строки с помощью специальной функции:

    import "fmt" ... length := len("hello") fmt.Println(length) // ВЫВОД: 5

    Так как Go использует кодировку UTF-8, длина строки соответствует количеству используемых байтов, а не число символов. Это связано с тем, что некоторые символы занимают 2 и более байта:

    import "fmt" ... length := len("привет") // указано 6 символов fmt.Println(length) // ВЫВОД: 12

    Например, вот так можно перебрать все байты на основе фактической (байтовой) длины строки:

    import "fmt" ... any_string := "привет" // ВЫВОД: d0 bf d1 80 d0 b8 d0 b2 d0 b5 d1 82 for i := 0; i < len(any_string); i++ { fmt.Printf("%x ", any_string[i]) // тут может быть некоторое действие }

    В некоторых практических случаях (в том числе и при определении схожести строк) может потребоваться последовательный ручной перебор всех символов строки. Сделать это можно с помощью цикла:

    import "fmt" ... for symbol_index, symbol_value := range "Hello For All Worlds" { fmt.Printf("Value: %c; Index: %d\n", symbol_value, symbol_index) // тут может быть некоторое действие }

    Вывод и форматирование строк

    Форматирование с базовыми типами

    Уже знакомый вам пакет fmt имеет специальные возможности для форматирования строк в момент их вывода в консоль. На самом деле его возможности не сильно отличаются от методов форматирования в других языках программирования — используются шаблоны (templates) и глаголы нотации (annotation verbs):

    import "fmt" ... // вывод переменной строки через подстановку %s any_string := "hello" result := fmt.Sprintf("%s world", any_string) fmt.Println(result) // ВЫВОД: hello world // вывод переменной числа через подстановку %d any_number := 13 result = fmt.Sprintf("there are %d worlds!", any_number) fmt.Println(result) // ВЫВОД: there are 10 worlds" // вывод переменной логики через подстановку %t any_boolean := true result = fmt.Sprintf("this is the %t world!", any_boolean) fmt.Println(result) // ВЫВОД: this is the true world!

    Обратите внимание, что для форматирования используется функция Sprintf, которая лишь возвращает строку, которая впоследствии выводится в консоль через Println.

    Возможно использование и более сложных шаблонов форматирования с использованием нескольких переменных:

    import "fmt" ... // вывод двух строк в одном шаблоне first_string := "hello" second_string := "world" result := fmt.Sprintf("%s %s", first_string, second_string) fmt.Println(result) // ВЫВОД: hello world // вывод трех чисел в одном шаблоне first_number := 10 second_number := 20 third_number := 30 result = fmt.Sprintf("%d and %d and %d", first_number, second_number, third_number) fmt.Println(result) // ВЫВОД: 10 and 20 and 30 // вывод двух логических в одном шаблоне first_boolean := true second_boolean := false result = fmt.Sprintf("if it is not %t therefore it means it is %t", first_boolean , second_boolean) fmt.Println(result) // ВЫВОД: if it is not true therefore it means it is false

    Вы можете также совместить несколько разных типов переменных в рамках одной функции форматирования:

    import "fmt" ... first_string := "hello" second_number := 13 third_boolean := true result := fmt.Sprintf("%s to all %d %t worlds", first_string, second_number, third_boolean) fmt.Println(result) // ВЫВОД: hello to all 13 true worlds

    Форматирование с бинарными данными

    Можно также выполнять особый вывод с преобразованием чисел в бинарный форма «нулей и единиц»:

    import "fmt" ... first_number := 13 second_number := 25 result := fmt.Sprintf("%b and %b", first_number, second_number) fmt.Println(result) // ВЫВОД: 1101 and 11001

    Нужен сервер для практики? Арендуйте VPS/VDS в России — root-доступ, NVMe, DDoS-защита и поддержка 24/7.

    VPS для проекта

    VPS с root-доступом, NVMe и поддержкой 24/7 на Simple-Server.

    StarterVDS

    490₽

    в месяц

    1 ядро

    1 ГБ RAM

    20 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Безлимитный трафик
    Заказать VPS
    Рекомендуем

    PerformanceVDS

    1190₽

    в месяц

    2 ядра

    4 ГБ RAM

    60 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Базовая DDoS-защита
    Заказать VPS

    Нужна другая конфигурация или чистый VPS без панели?

    Все тарифы VPS

    Похожие статьи, которые могут быть вам интересны