Golang: Генерация строк в циклах
В Go строки — неизменяемы (immutable). Это значит, что при каждой операции конкатенации создаётся новая строка, а не изменяется существующая:
s := "Hello"
s += " "
s += "world"
Код выше создает три строки в памяти, потому что строки в Go не модифицируются напрямую. Если таких операций много (например, при сборке HTML, SQL или при генерации отчёта), это приводит к лишним аллокациям и снижению производительности.
Для таких случаев стандартная библиотека Go предлагает эффективное решение — strings.Builder
.
strings.Builder
— это структура из пакета strings, предназначенная для эффективного построения строк. Он накапливает содержимое во внутреннем буфере, а финальную строку можно получить с помощью метода .String()
.
var builder strings.Builder
builder.WriteString("Hello")
builder.WriteString(" ")
builder.WriteString("world")
result := builder.String()
fmt.Println(result) // => Hello world
Для работы с рунами используется свой метод:
builder.WriteString("Hi")
builder.WriteByte(' ')
builder.WriteRune('世') // китайский символ
builder.WriteRune('界') // "界"
fmt.Println(builder.String()) // => Hi 世界
Почему Builder быстрее
Каждый вызов +
над строками в Go создает новую строку, копируя содержимое в новую память. Это дорого по производительности при большом числе операций. Builder же использует один буфер и растёт по мере необходимости, что сокращает число выделений памяти и операций копирования.
Пример: Объединение с разделителем
package main
import (
"fmt"
"strings"
)
func main() {
text := "hexlet"
var bld strings.Builder
for i, r := range text {
bld.WriteRune(r)
// Добавляем запятую, если это не последний символ
if i < len(text)-1 {
bld.WriteString(",")
}
}
result := bld.String()
fmt.Println(result) // => h,e,x,l,e,t
}
Задание
Напиши функцию FilterString()
, которая получает строку и символ. Она должна вернуть новую строку без всех букв, совпадающих с этим символом — неважно, большие они или маленькие (например, A
и a
считаются одинаковыми).
FilterString("If I look forward I win", 'i') // "f look forward wn"
FilterString("If I look forward I win", 'O') // "If I lk frward I win"
Для приведения символов к нижнему регистру используйте функцию unicode.ToLower()
:
import "unicode"
r := 'A'
unicode.ToLower(r) // 'a'
Полезное
Команда проекта находится в телеграм-сообществе. Там можно задать любой вопрос и повлиять на проект
Если вы зашли в тупик, то самое время поговорить с нашим асситентом Тота во вкладке "ИИ-помощник":
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи. В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в обратной связи нашего сообщества
Ваше упражнение проверяется по этим тестам
package solution
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFilterString(t *testing.T) {
a := assert.New(t)
a.Equal("f look forward wn", FilterString("If I look forward I win", 'i'))
a.Equal("If I lk frward I win", FilterString("If I look forward I win", 'O'))
a.Equal("Hxlt", FilterString("Hexlet", 'e'))
a.Equal("Hello", FilterString("Hello", 'x')) // Символ отсутствует
a.Equal("", FilterString("", 'a')) // Пустая строка
}
Решение учителя откроется через:
20:00
