DEV Community

Gino Luraschi
Gino Luraschi

Posted on

Novedades en Go 1.21 🚀

Introducción

Después de la versión 1.20, Go lanza la versión 1.21 con algunas pequeñas novedades para explotar un poco más el lenguaje, como siempre la nueva versión tiene retrocompatibilidad con versiones anteriores, por lo que cambiar a la nueva versión no debería impactar en lo que ya tengamos hecho. Sin más vamos a revisar cuales son las novedades en esta versión:

Cambios en el lenguaje

Min y Max

En esta nueva versión de Go encontramos funciones nuevas integradas como min y max, el cual toma un listado de valores y los compara devolviendo mínimo o máximo respectivamente.

package main

import "fmt"

func main() {
    x := 10
    y := 15
    mn := min(x, y) // m is the smaller of x and y
    fmt.Printf("The min is %d \n", mn)
    mx := max(x, y, 10) // m is the larger of x and y but at least 10
    fmt.Printf("The max is %d \n", mx)
    c := max(1, 2.0, 10) // c == 10.0 (floating-point kind)
    fmt.Printf("The max is %f \n", c)
    f := max(0, float32(x)) // type of f is float32
    fmt.Printf("The max is %f \n", f)
    // var s []string
    // _ = min(s...)// invalid: slice arguments are not permitted
    t := max("", "foo", "bar") // t == "foo" (string kind)
    fmt.Printf("The max is %s \n", t)
}
Enter fullscreen mode Exit fullscreen mode

Clear

Otra novedad de la nueva versión de Go, es la función clear

package main

import "fmt"

func main() {
    var mapToClear = map[string]int{"k1": 1, "k2": 2, "k3": 3}
    clear(mapToClear) // Elimina todos los pares Key-Value (len(m) == 0)
    fmt.Printf("%v \n", mapToClear)
    var arr = []int{1, 2, 3, 4}
    clear(arr) // Vuelve todos los elementos al valor Zero del tipo
    fmt.Printf("%v \n", arr)
    /*
        var t = struct {
            // Name       string // Dato invalido para limpiar
            mapToClear map[string]int
        }{
            // Name:       "test",
            mapToClear: map[string]int{"k1": 1, "k2": 2, "k3": 3},
        }
         clear(t) // No se puede hacer esto, tira un error ya que t debe ser del tipo map o slice
    */
}

Enter fullscreen mode Exit fullscreen mode

Otras cositas del lenguaje

En cuanto a los genéricos, se hicieron mejoras en cuanto a la inferencia de los tipos. Ahora se incluye una explicación sobre el proceso y como funciona en la documentación oficial.

Algo que planean hacer, que esta incluido en la version 1.21 de Go como experimental, es arreglar la captura de variables en los ciclos for, para eso recomiendan ir al caso escrito en LoopvarExperiment

Novedades de la SDK

Paquete log/slog

una de las cositas más interesantes que sumó esta nueva versión es el nuevo paquete log/slog para logging, el cual agrega funcionalidades a nuestro logging sin necesidad de sumar una librería:

package main

import (
    "log"
    "log/slog"
)

func main() {
    slog.Info("hello", "count", 3)
    // 2009/11/10 23:00:00 INFO hello count=3
    log.Println("hello", "count", 3)
    // 2009/11/10 23:00:00 hello count 3

    slog.Info("hello", "count", 1)
    // 2009/11/10 23:00:00 INFO hello count=1
    slog.Error("hello", "count", 2)
    // 2009/11/10 23:00:00 ERROR hello count=2
    slog.Warn("hello", "count", 3)
    // 2009/11/10 23:00:00 WARN hello count=3
    slog.Debug("hello", "count", 4)
    // 2009/11/10 23:00:00 DEBUG hello count=4

    // Print as json
    h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug})
    slog.SetDefault(slog.New(h))
    slog.Debug("it's a debug log")
}
Enter fullscreen mode Exit fullscreen mode

Paquete slice

Nuevo paquete slice para manejo de slices justamente, esta incluye funcionalidades interesantes como métodos de ordenamiento o de búsquedas:

package main

import (
    "fmt"
    "slices"
)

func main() {
    arr := []int{8, 2, 4, 5, 1}
    slices.Sort(arr) // Es mutable, por lo que cambia el array original
    fmt.Println(arr) // [1 2 4 5 8]

    index, found := slices.BinarySearch(arr, 2)
    fmt.Println(found, index) // true 1
}
Enter fullscreen mode Exit fullscreen mode

Paquete maps

Tambien se suma un nuevo paquete maps para los mapas pero con menos funciones:

package main

import (
    "fmt"
    "maps"
)

func main() {
    mapEx := map[string]int{"k1": 1, "k2": 2}
    mapClone := maps.Clone(mapEx)
    fmt.Println(mapClone) // map[k1:1 k2:2]

    equal := maps.Equal(mapEx, mapClone)
    fmt.Println(equal) // true
}
Enter fullscreen mode Exit fullscreen mode

Paquete cmp

Tambien se agrega un nuevo paquete cmp para comparar elementos:

package main

import (
    "cmp"
    "fmt"
)

func main() {
    // -1 if x is less than y,
    // 0 if x equals y,
    // +1 if x is greater than y.
    x := 5
    y := 10
    res := cmp.Compare(x, y)
    fmt.Println(res) // -1
    res = cmp.Compare(y, x)
    fmt.Println(res) // 1
    res = cmp.Compare(5, x)
    fmt.Println(res) // 0

    isLess := cmp.Less(5, x)
    fmt.Println(isLess) // false
    isLess = cmp.Less(x, y)
    fmt.Println(isLess) // true
}
Enter fullscreen mode Exit fullscreen mode

Profile Guided Optimization

La herramienta Profile Guided Optimization (PGO) anunciada en la versión 1.20 ahora está disponible sin necesidad de habilitarla. Con esta herramienta vamos a poder construir paquetes más optimizados. Incluso se ha medido el impacto en varios programas y se ve mejoras del 2% al 7%.

Mejoras en la performance

Además de lo mencionado en PGO, podemos ver:

  • El compilador de go fue reconstruido en la nueva versión con PGO habilitado, lo que logró hacerlo 2-4% más rápido dependiendo del sistema que lo ejecute.
  • Debido a la mejora en el Garbage Collector, se detecta una reducción del 40% en la latencia de cola.
  • Ahora la recolección de runtime/trace ahora reduce el costo para arquitectura arm64 y amd64.

Conclusión

Estas son algunas de las novedades que podemos detectar de la nueva versión de go, para más detalle puede ir a leer el blog oficial en https://go.dev/blog/go1.21. Espero les ayude este resumen a poder comprenderlo.

Top comments (0)