Что нового в Go 1.23: Итераторы, Unique, Телеметрия, улучшения таймеров и другое

Что нового в Go 1.23: Итераторы, Unique, Телеметрия, улучшения таймеров и другое
/assets/blog/authors/asanov_small.jpg
Ildar Asanov
#golang#updates
  • Итераторы: iter и slices
  • Новый пакет unique
  • Улучшение таймеров
  • Телеметрия в Go 1.23
  • Поддержка новых платформ

Итераторы: 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) // [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"
}

Это полезно в ситуациях, когда одно и то же значение используется многократно, и важно минимизировать избыточное потребление памяти.

Улучшение таймеров

Изменена реализация time.Timer и 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("Тикер остановлен")
}

Телеметрия в Go 1.23

А вот это уже действительно интересно. Добавлена телеметрия - теперь можно добровольно отправлять анонимные данные об использовании инструментов Go. Вот пример интеграции с 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() {
    exporter, err := otlptracehttp.New(context.Background(),
        otlptracehttp.WithEndpoint("your-apm-server:8200"),
        otlptracehttp.WithInsecure(),
    )
    if err != nil {
        log.Fatal(err)
    }

    tp := trace.NewTracerProvider(
        trace.WithBatcher(exporter),
        trace.WithResource(resource.NewWithAttributes(
            semconv.SchemaURL,
            semconv.ServiceNameKey.String("my-service"),
        )),
    )

    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("Телеметрия отправлена в APM")
}

Поддержка новых платформ

Добавлена экспериментальная поддержка OpenBSD на RISC-V 64-bit.

Спасибо за прочтение! Не забудьте подписаться на мой телеграмм канал, где вы найдете больше полезной информации о разработке: @asanov_tech{:target="_blank" rel="nofollow"}

More Stories