Гид по технологиям

Форматирование строк в Go — полное руководство

7 min read Go Обновлено 22 Nov 2025
Форматирование строк в Go — руководство
Форматирование строк в Go — руководство

Набор цифр и букв на синем фоне, иллюстрация форматирования

Что такое форматирование строк в Go

Форматирование строк — это процесс подстановки значений в шаблонную строку с использованием специальных плейсхолдеров, называемых глаголами (verbs). В Go этот механизм реализован в пакете fmt и по синтаксису похож на printf в C и других языках.

Определение: глагол форматирования — символ или последовательность символов в формате (начинающаяся с %), указывающая, как отобразить соответствующее значение.

Короткая памятка:

  • %v — значение в «дефолтном» представлении;
  • %T — тип значения;
  • %% — литерал процента.

Важно: Print и Println не интерпретируют глаголы форматирования; для них используйте Printf или Sprintf.

Основные функции пакета fmt

Пакет fmt содержит несколько важнейших функций для форматирования и вывода:

  • fmt.Printf(format string, a …interface{}) (int, error) — форматирует и выводит в стандартный вывод; возвращает число записанных байт и ошибку.
  • fmt.Sprintf(format string, a …interface{}) string — форматирует и возвращает результат как строку.
  • fmt.Fprintf(w io.Writer, format string, a …interface{}) (int, error) — форматирует и записывает результат в io.Writer.
  • fmt.Fscanf(r io.Reader, format string, a …interface{}) (int, error) — сканирует из io.Reader согласно формату.

Примеры:

// fmt.Printf выводит форматированную строку в stdout
fmt.Printf("This is a test %v\n", 90)

// fmt.Sprintf возвращает строку
result := fmt.Sprintf("This is a test %v", 90)
fmt.Println(result)

// fmt.Fprintf записывает в writer, реализующий io.Writer
// result, err := fmt.Fprintf(writer, "This is a test %v", 90)

// fmt.Fscanf читает из reader и декодирует
// var take string
// reader := strings.NewReader("This is a test")
// read, err := fmt.Fscanf(reader, "%v", &take)

Примечание: в большинстве практических случаев ошибки от Printf игнорируют, но для Fprintf/Fscanf, особенно при записи в сетевые/файловые объекты, проверять err обязательно.

Общие глаголы форматирования и примеры

Ниже — перечень часто используемых глаголов и их назначение. Используйте %v как универсальный вариант, но при необходимости выбирайте точный глагол для контроля формата.

type Person struct {
  Name       string
  Age        int
  IsLoggedIn bool
}

instance := Person{
  Name:       "John Doe",
  Age:        34,
  IsLoggedIn: true,
}

result := fmt.Sprintf("This is a struct formatting example %+v", instance)
fmt.Println(result)

Ожидаемый вывод:

This is a struct formatting example {Name:John Doe Age:34 IsLoggedIn:true}

Таблица: основные глаголы по типам

Тип данныхГлаголОписание
boolean%ttrue/false
целые (signed)%dдесятичное целое (int, int8 и т.д.)
целые (unsigned)%d (в контексте %v), %#x с %#vuint, uint8 и т.д. (иногда в hex с префиксом)
плавающие%gfloat32, complex64 и т.д. (общее представление)
строка%sстрока
канал%pchan (адрес/представление канала)
указатель%pуказатель (адрес в hex)

Примечание: регистр глагола имеет значение — %x и %X дают разный регистр букв в шестнадцатеричном выводе.

Форматирование целых чисел (integer)

Глаголы, полезные при работе с целыми числами и представлениями в разных системах счисления:

ГлаголНазначение
%bдвоичный (base 2)
%cсимвол, соответствующий Unicode-коду
%dдесятичный (base 10)
%oвосьмеричный (base 8)
%Oвосьмеричный с префиксом 0o
%qодиночная кавычка, безопасно экранированный литерал символа
%xшестнадцатеричный (нижний регистр)
%Xшестнадцатеричный (верхний регистр)
%UUnicode в формате U+1234

Пример:

result := fmt.Sprintf("Integer formatting example: %d, hex: %x, bin: %b", 90, 90, 90)
fmt.Println(result)

Форматирование чисел с плавающей точкой (float)

Глаголы для плавающих чисел и комплексных типов:

ГлаголОписание
%bформат без десятичной точки с экспонентой степени двойки (strconv.FormatFloat ‘b’)
%eнаучная нотация, например -1.234456e+78
%Eнаучная нотация с большим E
%fдесятичная точка, без экспоненты, например 123.456
%Fсиноним %f
%g%e для больших экспонент, %f иначе (умный выбор)
%G%E для больших экспонент, %F иначе
%xшестнадцатеричная нотация со степенями двойки
%Xверхний регистр для шестнадцатеричной нотации

Пример:

result := fmt.Sprintf("This is a floating point example %f", 432.9503)
fmt.Println(result)

Форматирование строк и слайсов байт

Для строк и []byte используйте следующие глаголы:

ГлаголОписание
%sпоследовательность байт (без интерпретации)
%qстрока в двойных кавычках с безопасным экранированием
%xhex, 2 символа на байт (нижний регистр)
%Xhex, 2 символа на байт (верхний регистр)

Пример:

score := "example"
result := fmt.Sprintf("This is a string formatting example %s", score)
fmt.Println(result)

Результат форматирования целых чисел

Флаги, ширина и точность

Глаголы можно комбинировать с флагами и спецификациями ширины/точности для точного контроля вывода:

  • %-10s — выровнять влево в поле ширины 10;
  • %10s — выровнять вправо в поле ширины 10;
  • %.2f — вывести 2 знака после запятой для float;
  • %010d — дополнить целое слева нулями до ширины 10.

Примеры:

fmt.Printf("|%10s|\n", "go")   // |        go|
fmt.Printf("|%-10s|\n", "go")  // |go        |
fmt.Printf("%.2f\n", 3.14159)    // 3.14
fmt.Printf("%010d\n", 42)        // 0000000042

Когда форматирование может подвести (примеры проблем)

  • Неправильный глагол для типа: использование %d для строки приведёт к ошибке компиляции или неожиданному выводу.
  • Несогласованность числа аргументов и плейсхолдеров: лишние аргументы игнорируются, отсутствующие приводят к ошибки во время выполнения.
  • Параллельный вывод в лог и fmt: в многопоточных приложениях смешение записей возможно без синхронизации.
  • Форматирование структур %v по умолчанию не раскрывает приватные поля пакета.

Контрпример: Sprintf(“%d”, “str”) не отформатирует строку как число — это ошибка типов во время компиляции или форматирования.

Альтернативные подходы и когда их использовать

  • strings.Builder — эффективная конкатенация строк без форматирования, если требуется простое сложение.
  • bytes.Buffer — для побайтной сборки вывода в память и последующей записи.
  • text/template / html/template — когда нужно безопасно генерировать шаблонный текст (например, HTML), избегая XSS.
  • fmt.Formatter интерфейс — для пользовательской логики форматирования типов (реализуйте Format(f fmt.State, c rune)).

Выбор:

  • Нужен быстрый, контролируемый формат — fmt.Sprintf/Printf.
  • Нужна производительность при массовых конкатенациях — strings.Builder.
  • Нужна шаблонная генерация с логикой — text/template.

Хитрости и эвристики (mental models)

  • Всегда думайте: “какой тип данных и как я хочу его видеть”. Если не уверены — начните с %v, затем уточняйте.
  • Используйте %+v для структур, чтобы увидеть имена полей.
  • Для отладки часто достаточно %#v — показывает Go-литерал (иногда полезно при логах).
  • Для логирования: используйте fmt.Fprintf(loggerWriter, …) или пакет log с форматированием.

Мини-методология выбора глагола (шаги)

  1. Определите тип значения (int, float, string, struct, pointer).
  2. Выберите семантику вывода (читаемое, машинное, debug, hex, unicode).
  3. Примените подходящий глагол (%d, %f, %s, %v, %#v, %q и т.д.).
  4. При необходимости задайте ширину и точность.
  5. Добавьте тесты, проверяющие формат в edge-кейсах (нулевые значения, большие числа, спецсимволы).

Чек-листы для ролей

Developer:

  • Проверил типы аргументов и соответствие глаголов.
  • Добавил тесты на граничные случаи (nil, пустая строка, отрицательные числа).
  • Использует fmt.Sprintf для формирования сообщений, а не ручную конкатенацию.

SRE / Ops:

  • Логи форматируются однородно (JSON или форматированный текст) для парсинга.
  • Проверена стабильность вывода при высоких нагрузках (race conditions).

Tech writer:

  • Проверил экранирование спецсимволов при формировании пользовательских сообщений.

Тестовые сценарии и критерии приёмки

Критерии приёмки:

  • Форматирование целых, float и строк соответствует требованиям спецификации.
  • Наличие проверок на nil и ошибки при использовании Fprintf/Fscanf.
  • Логи не теряются при конкурентном доступе.

Пример теста (table-driven):

func TestFormatInteger(t *testing.T) {
  tests := []struct {
    in   int
    want string
  }{
    {90, "90"},
    {0, "0"},
    {-1, "-1"},
  }
  for _, tt := range tests {
    got := fmt.Sprintf("%d", tt.in)
    if got != tt.want {
      t.Fatalf("got %s want %s", got, tt.want)
    }
  }
}

Сниппет: реализация пользовательского форматирования

// Реализуем fmt.Formatter для кастомного типа
type IPAddr [4]byte

func (ip IPAddr) Format(s fmt.State, verb rune) {
  switch verb {
  case 'v':
    if s.Flag('#') {
      fmt.Fprintf(s, "%#v", [4]byte(ip))
      return
    }
    fmt.Fprintf(s, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
  case 's':
    fmt.Fprintf(s, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
  }
}

Совместимость и миграция

  • Форматирующие глаголы и поведение пакета fmt стабильно между релизами Go; кардинальные изменения редки.
  • При миграции с других языков (например, Python/Java) учитывайте различия в спецификациях: Go использует %v/%#v/%+v и строгую типизацию аргументов.
  • Если используете внешний логгер (zap, zerolog), лучше придерживаться их API, а не fmt, чтобы сохранить структурированные логи.

Практические советы по производительности

  • fmt.Sprintf выделяет память для результирующей строки; при большом количестве конкатенаций отдавайте предпочтение strings.Builder.
  • Для критичных по производительности участков измеряйте через pprof/benchmarks.

Риски и меры смягчения

  • Риск: неправильный глагол приводит к некорректному выводу в проде. Митигирование: автотесты и статические проверки.
  • Риск: конкурентный доступ к глобальным writer-объектам. Митигирование: синхронизация или использование потокобезопасных логгеров.

Частые ошибки и советы по отладке

  • Ошибка: используете fmt.Println вместо fmt.Printf — глаголы не сработают. Решение: замените на fmt.Printf или fmt.Sprintf.
  • Ошибка: не экранируете пользовательский ввод при вставке в формат — риск инъекций в шаблоны/логи. Решение: валидируйте и экранируйте данные.
  • Для отладки используйте %#v, чтобы увидеть Go-литерал значения.

Краткая сводка

  • Пакет fmt — основной инструмент для форматирования строк в Go.
  • Выбор глагола зависит от типа и требуемого представления.
  • Для производительных операций используйте strings.Builder; для шаблонов — text/template.
  • Тесты и проверка ошибок обязательны при работе с Fprintf/Fscanf и внешними writer/reader.

Вывод: понимание глаголов форматирования и возможностей fmt — обязательный навык для каждого Go-разработчика. При правильном выборе инструментов вы получите читаемый, безопасный и прогнозируемый вывод.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Обновление видеодрайвера для Rainbow Six Siege
Windows

Обновление видеодрайвера для Rainbow Six Siege

Ограничение частоты запросов в ASP.NET Core
Backend

Ограничение частоты запросов в ASP.NET Core

Исправление лагов Android: TRIM и LagFix
Mobile

Исправление лагов Android: TRIM и LagFix

Семафоры в Bash: что это и как реализовать
Bash

Семафоры в Bash: что это и как реализовать

Что делать при перегреве PS5
Гайды

Что делать при перегреве PS5

Разбить и собрать большие файлы — лучшие инструменты
Утилиты

Разбить и собрать большие файлы — лучшие инструменты