Что нового в Go 1.23: Итераторы, Unique, Телеметрия, улучшения таймеров и другое
13 августа 2024 года вышел очередной релиз новой версии Golang - Go 1.23, включающий улучшения как в языке, так и в стандартной библиотеке.
Перед прочтением рекомендую подписаться на мой телеграмм канал, где вы сможете найти актуальные новости, примеры и хаки в мире разработки: @asanov_tech
Итераторы: iter и slices
Введены итераторы для работы с пользовательскими последовательностями данных. Появился новый пакет iter, а также функции для работы с итераторами в пакетах slices и maps. Теперь можно, например, обрабатывать ключи карты с помощью итераторов.
Пример использования итераторов:
package main import ( "fmt" "golang.org/x/exp/maps" "golang.org/x/exp/slices" ) func main() { // Создаём карту m := map[string]int{ "apple": 5, "banana": 2, "cherry": 7, } // Получаем все ключи карты через итератор keys := maps.Keys(m) // Сортируем ключи sortedKeys := slices.Sorted(keys) // Выводим отсортированные ключи fmt.Println(sortedKeys) }
Объяснение:
> maps.Keys(m) возвращает итератор по ключам карты m.
> slices.Sorted(keys) сортирует ключи.
> В результате программа выведет отсортированный список ключей: [apple banana cherry].
Этот код демонстрирует основные функции нового пакета iter, который используется для работы с коллекциями данных, например, картами и срезами.
Новый пакет unique
Позволяет “канонизировать” значения, создавая одну общую копию для одинаковых объектов, что помогает сократить использование памяти.
Пример использования пакета unique в Go 1.23:
package main import ( "fmt" "golang.org/x/exp/unique" ) func main() { // Создаем объект для канонизации строк u := unique.Make[string]() // Канонизируем несколько строк handle1 := u.Handle("apple") handle2 := u.Handle("banana") handle3 := u.Handle("apple") // Сравниваем канонизированные строки fmt.Println(handle1 == handle3) // true fmt.Println(handle1 == handle2) // false // Выводим оригинальные значения fmt.Println(handle1.Value()) // "apple" fmt.Println(handle2.Value()) // "banana" }
Объяснение:
• Пакет unique позволяет “канонизировать” значения, то есть создавать общие объекты для одинаковых данных. В примере строка "apple" была канонизирована дважды, но handle1 и handle3 ссылаются на одну и ту же строку, что показывает эффективное использование памяти.
• Функция u.Handle("apple") возвращает объект Handle[string], который используется для сравнения и доступа к значению.
Это полезно в ситуациях, когда одно и то же значение используется многократно, и важно минимизировать избыточное потребление памяти.
Телеметрия в Go 1.23 / Telemetry
А вот это уже действительно интересно. Добавлена телеметрия — теперь можно добровольно отправлять анонимные данные об использовании инструментов Go, что поможет улучшить качество сборки и быстрее находить баги. Также появились новые команды, такие как
go env -changed
для отображения измененных переменных окружения.
Ниже подробнее расскажу на примерах как это использовать с практическими примерами.
Улучшение таймеров
Изменена реализация time.Timer и time.Ticker, что должно улучшить производительность. Тут с точки зрения интерфейса нового ничего нет, но под капотом разработчики гошки значительно увеличили скорость. Однако, я всё же приведу простой пример использования timer и tick: Пример: Повторяющийся таймер с time.Ticker
package main import ( "fmt" "time" ) func main() { // Создаем тикер, который срабатывает каждые 500 миллисекунд ticker := time.NewTicker(500 * time.Millisecond) // Запускаем цикл для обработки событий тикера go func() { for t := range ticker.C { fmt.Println("Тик в:", t) } }() // Останавливаем тикер через 2 секунды time.Sleep(2 * time.Second) ticker.Stop() fmt.Println("Тикер остановлен") }
Объяснение:
• time.NewTicker создаёт тикер, который генерирует события каждые 500 миллисекунд.
• Мы обрабатываем события из канала тикера ticker.C.
• По истечении 2 секунд тикер останавливается с помощью ticker.Stop().
Поддержка новых платформ
Добавлена экспериментальная поддержка OpenBSD на RISC-V 64-bit.
Эти и другие обновления направлены на повышение удобства работы с языком, оптимизацию производительности и улучшение стандартной библиотеки. Полные подробности можно найти в релизных заметках Go 1.23 на официальном сайте.sd
Как интегрировать обновелния телеметрии в Go 1.23 с Jaeger?
Чтобы интегрировать Go с OpenTelemetry и включить его в APM и Jaeger, можно следовать следующим шагам:
1. Установка OpenTelemetry для Go
Сначала нужно установить библиотеку OpenTelemetry для Go:
go get go.opentelemetry.io/otel go get go.opentelemetry.io/otel/sdk go get go.opentelemetry.io/otel/exporters/trace/jaeger
Эти пакеты предоставляют необходимые инструменты для работы с OpenTelemetry, включая SDK и экспортёры для отправки данных в Jaeger.
2. Пример настройки трейсинга с OpenTelemetry и отправки данных в Jaeger
package main import ( "context" "log" "time" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/resource" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" ) func initTracer() func() { // Настраиваем экспортёр OTLP для отправки в Elastic APM exporter, err := otlptracehttp.New(context.Background(), otlptracehttp.WithEndpoint("your-apm-server-url:8200"), // Укажите URL вашего Elastic APM otlptracehttp.WithInsecure(), // Если используете HTTP, уберите для HTTPS ) if err != nil { log.Fatal(err) } tp := trace.NewTracerProvider( trace.WithBatcher(exporter), trace.WithResource(resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String("your-service-name"), )), ) otel.SetTracerProvider(tp) return func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatal(err) } } } func main() { cleanup := initTracer() defer cleanup() tracer := otel.Tracer("example-tracer") // Пример использования трейсинга ctx, span := tracer.Start(context.Background(), "example-operation") time.Sleep(1 * time.Second) span.End() log.Println("Telemetry sent to Elastic APM") }
3. Включение OpenTelemetry в APM (например, Datadog или другие)
OpenTelemetry может работать с разными APM системами. Для этого достаточно изменить экспортёр на нужную платформу (например, Datadog или Zipkin). Используйте нужный экспортёр OpenTelemetry, который интегрирован с вашей APM платформой. Для Datadog, например, можно использовать экспортёр datadog/opentelemetry-exporter.
4. Конфигурация Jaeger
Jaeger можно запустить локально через Docker для тестирования:
docker run -d --name jaeger \ -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \ -p 5775:5775/udp \ -p 6831:6831/udp \ -p 6832:6832/udp \ -p 5778:5778 \ -p 16686:16686 \ -p 14268:14268 \ -p 14250:14250 \ -p 9411:9411 \ jaegertracing/all-in-one:1.22
Как интегрировать обновелния телеметрии в Go 1.23 с APM от Elastic?
1. Настройка Elastic APM
Elastic APM поддерживает OpenTelemetry, что делает интеграцию более гибкой. Прежде чем начать, убедитесь, что Elastic APM настроен и работает, и что у вас есть доступ к Elastic APM серверу.
2. Установка OpenTelemetry для Go
Go 1.23 включает встроенную телеметрию, но для отправки данных в Elastic APM нам нужно воспользоваться OpenTelemetry. Установите необходимые библиотеки OpenTelemetry:
go get go.opentelemetry.io/otel go get go.opentelemetry.io/otel/sdk go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
3. Конфигурация экспорта телеметрии в Elastic APM через OpenTelemetry
Elastic APM поддерживает протокол OTLP, который используется OpenTelemetry для отправки трейсингов и метрик. Настроим экспорт данных телеметрии из Go в Elastic APM:
package main import ( "context" "log" "time" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/sdk/resource" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" ) func initTracer() func() { // Настраиваем экспортёр OTLP для отправки в Elastic APM exporter, err := otlptracehttp.New(context.Background(), otlptracehttp.WithEndpoint("your-apm-server-url:8200"), // Укажите URL вашего Elastic APM otlptracehttp.WithInsecure(), // Если используете HTTP, уберите для HTTPS ) if err != nil { log.Fatal(err) } tp := trace.NewTracerProvider( trace.WithBatcher(exporter), trace.WithResource(resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String("your-service-name"), )), ) otel.SetTracerProvider(tp) return func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatal(err) } } } func main() { cleanup := initTracer() defer cleanup() tracer := otel.Tracer("example-tracer") // Пример использования трейсинга ctx, span := tracer.Start(context.Background(), "example-operation") time.Sleep(1 * time.Second) span.End() log.Println("Telemetry sent to Elastic APM") }
4. Запуск Elastic APM серверов и просмотр трейсингов
1. Убедитесь, что Elastic APM сервер работает и настроен для приёма данных OTLP.
2. После запуска приложения, данные трейсинга будут отправляться в Elastic APM. Вы сможете их просматривать в разделе APM в Kibana.
5. Включение телеметрии Go 1.23
Для активации встроенной телеметрии Go 1.23 можно использовать команду:
go telemetry on
Заключение
Интеграция Elastic APM с Go 1.23 через OpenTelemetry позволяет не только использовать встроенные функции телеметрии Go, но и отправлять данные в Elastic для глубокого анализа производительности и ошибок.
аки в мире разработки: https://t.me/asanov_tech
Комментарии
Отправить комментарий