- Esta versión se centra en métodos genéricos, mejora los literales de structs y la inferencia de tipos, y agrega funciones prácticas en toda la biblioteca estándar, el runtime y la toolchain
- La asignación de memoria especializada por tamaño reduce hasta un 30% el costo de algunas asignaciones de menos de 80 bytes; en programas intensivos en asignaciones se espera una mejora de rendimiento de alrededor del 1% y un aumento del binario de unos 60 KB
encoding/json/v2queda disponible oficialmente y elencoding/jsonexistente también usa v2 internamente; se agregan un paquete UUID estándar y firmas ML-DSA basadas en FIPS 204- El perfil
goroutineleak, las etiquetas pprof en tracebacks,synctest.Sleeppara tiempo virtual y un servidor HTTP de pruebas en memoria facilitan el diagnóstico y las pruebas de concurrencia - El cambio de los canales de timers a no bufferizados, el agotamiento automático del cuerpo de respuestas HTTP y el endurecimiento de las restricciones de
//go:linknamepueden afectar código existente, por lo que se necesita una verificación de compatibilidad antes de migrar a Go 1.27
Lenguaje y sistema de tipos
- Los métodos genéricos, eje central de Go 1.27, pueden declarar sus propios parámetros de tipo independientes del receiver
- Antes, solo las funciones de nivel superior podían ser genéricas, por lo que incluso las operaciones pertenecientes a un tipo debían escribirse como funciones de paquete
- Operaciones como
Box[T].Map[U], que devuelven un tipo de elemento distinto al de entrada, pueden definirse como métodos - Las interfaces todavía no pueden declarar métodos con parámetros de tipo, y tampoco se puede implementar una interfaz mediante métodos genéricos
- En las claves de literales de structs se pueden usar selectores de campo válidos, no solo nombres de campos de nivel superior
- En structs embebidos, los campos promovidos pueden inicializarse directamente, como
User{ID: 7}
- En structs embebidos, los campos promovidos pueden inicializarse directamente, como
- La inferencia de tipos de funciones se amplía a conversiones y literales compuestos
- Infere los argumentos de tipo de funciones genéricas a partir del tipo de función esperado, como en
[]func([]int) int{first, last} - Antes era necesario instanciarlas directamente, como
first[int]ylast[int]
- Infere los argumentos de tipo de funciones genéricas a partir del tipo de función esperado, como en
Runtime y rendimiento
- El compilador llama a rutinas de asignación especializadas por tamaño para reducir hasta un 30% el costo de algunas asignaciones de memoria de menos de 80 bytes
- En programas reales intensivos en asignaciones, se espera una mejora general de rendimiento de alrededor del 1%
- No hace falta modificar el código, pero el binario crece unos 60 KB independientemente de la carga de trabajo
- Puede desactivarse con
GOEXPERIMENT=nosizespecializedmalloc, aunque esta opción se eliminará en Go 1.28
- Se agregan tres optimizaciones del compilador habilitadas por defecto
- Un pase de flujo de datos de known bits que rastrea bits que con certeza son 0 o 1 en un valor y elimina operaciones redundantes
- Movimiento de código invariante de bucle, que saca del loop cálculos que no cambian durante la iteración
- Compilación de
switchque cumplan ciertas condiciones como tablas de búsqueda, incluyendofallthrough
- El experimento
GOEXPERIMENT=mapsplitgroupcambia la disposición en memoria de los grupos de mapas deKVKVKVKVaKKKKVVVV, y está desactivado por defecto - El linker mueve los descriptores de tipo y los itab a una sección dedicada
.go.type, y eliminatypelinkseitablinks- Como
reflect.typelinksdevuelve tipos en lugar de offsets, pueden verse afectadas las bibliotecas que acceden a este símbolo mediante//go:linkname
- Como
Diagnóstico de goroutines y profiling
- Los módulos cuyo
go.modindique Go 1.27 o posterior muestran etiquetas deruntime/pprofen el encabezado de goroutines de los tracebacks- Contextos agregados con
pprof.Do, como{request: 42}, aparecen en volcados de fallos,SIGQUITy salidas deruntime.Stack - Para evitar que etiquetas sensibles queden expuestas en tracebacks, se puede seguir usando
GODEBUG=tracebacklabels=0
- Contextos agregados con
- El detector de fugas de goroutines, que en Go 1.26 era experimental, pasa a ser el perfil oficial
goroutineleak- Ejecuta el GC para encontrar goroutines que nunca podrán avanzar, por ejemplo en canales o mutexes, e imprime sus stacks
- En servicios puede recopilarse mediante el endpoint
/debug/pprof/goroutineleak, sin requerirGOEXPERIMENT
Criptografía e identificadores
- El nuevo paquete crypto/mldsa implementa las firmas poscuánticas ML-DSA de FIPS 204
- Los tres conjuntos de parámetros
MLDSA44,MLDSA65yMLDSA87equilibran tamaño de claves y firmas con nivel de seguridad - También se agrega ML-DSA a claves y firmas de
crypto/x509, y a los métodos de firma TLS 1.3 decrypto/tls
- Los tres conjuntos de parámetros
- El nuevo paquete uuid de la biblioteca estándar genera y parsea UUID RFC 9562 con números aleatorios criptográficamente seguros
uuid.New()elige el método adecuado para usos generales;NewV4()crea UUID puramente aleatorios yNewV7()crea UUID ordenados por tiempo de generación- Los UUID basados en aleatoriedad son comparables, por lo que se puede usar
==directamente - Los UUID v7, ordenables temporalmente, son adecuados como claves de base de datos
JSON y APIs de procesamiento de datos
- encoding/json/v2 y el paquete de bajo nivel
encoding/json/jsontextse ofrecen sinGOEXPERIMENT=jsonv2- El
encoding/jsonv1 existente también usa internamente la implementación v2 - Mantiene el comportamiento existente salvo por algunos textos de mensajes de error, por lo que no hace falta migrar
- Si hay problemas de compatibilidad, se puede restaurar la implementación v1 original con
GOEXPERIMENT=nojsonv2 - Por rendimiento, v2 no ordena por defecto las claves de mapas, así que en pruebas que requieran salida estable debe especificarse
json.Deterministic
- El
strings.CutLastybytes.CutLastdividen valores tomando como referencia el último separador- Si no hay separador, devuelven la entrada completa, una segunda parte vacía y
false
- Si no hay separador, devuelven la entrada completa, una segunda parte vacía y
- El
Hasher[T]genérico dehash/maphashdefine en conjunto la estrategia de hash e igualdad de los valores- Valores iguales deben tener siempre el mismo hash
- Se ofrece
ComparableHasher[T]para tipos comparables, y también se pueden implementar estrategias personalizadas, como strings sin distinguir mayúsculas y minúsculas
math/big.Int.Dividecalcula cociente y resto juntos aplicando un modo de redondeo explícito entreTrunc,Floor,RoundyCeil- El resto también cambia según el modo de redondeo, lo que complementa en código financiero y numérico la limitación de truncamiento hacia cero de
QuoyModexistentes
- El resto también cambia según el modo de redondeo, lo que complementa en código financiero y numérico la limitación de truncamiento hacia cero de
math/rand/v2.(*Rand).Ngenera, desde su propia fuente*Rand, números aleatorios con límite de rango para tipos enteros o de duración
SIMD portable
- El paquete experimental simd ofrece una API SIMD independiente del tamaño del vector y se habilita con
GOEXPERIMENT=simd- En entornos compatibles compila a instrucciones vectoriales de hardware reales; de lo contrario, se reemplaza por emulación en Go puro
- La cantidad de lanes de tipos como
Float32sno es fija, sino que sigue el ancho de hardware de cada máquina
- La biblioteca estándar ya usa intrínsecos internos de
simd/archsimdMemHash32,MemHash64yStrHashde los mapas Swiss Table se reimplementaron sobre la nueva base SIMD
Pruebas deterministas
testing/synctest.Sleepavanza el tiempo virtual y espera a que todas las goroutines se estabilicen en una sola operación- Dentro de una burbuja
synctest, el tiempo real no transcurre, por lo que una espera de 2 segundos termina al instante - Reemplaza el código repetitivo que combinaba
time.Sleepysynctest.Wait
- Dentro de una burbuja
httptest.NewTestServerejecuta un servidor sobre una red virtual en memoria en lugar de un puerto TCP realsrv.Client()se conecta directamente al handler mediante pipes dentro del proceso- Como se limpia automáticamente con
t.Cleanup, no hace faltadefer srv.Close() - Combinado con
testing/synctest, incluso los viajes de ida y vuelta HTTP pueden probarse de forma rápida y determinista en tiempo virtual
Cambios de red y compatibilidad
- Los canales devueltos por
time.After,time.NewTimer,time.NewTickery similares pasan a ser siempre canales síncronos sin buffer- Se elimina la opción GODEBUG
asynctimerchan, que restauraba el comportamiento antiguo con buffer
- Se elimina la opción GODEBUG
- En HTTP/1,
http.Response.Body.Closelee el cuerpo no consumido hasta un límite conservador para ayudar a reutilizar la conexión- Si se dependía de
Closepara terminar anticipadamente una descarga grande, debe desactivarse la reutilización conTransport.DisableKeepAlives
- Si se dependía de
- Los servidores HTTP/2 entienden las prioridades de cliente de RFC 9218 y procesan primero los streams de mayor prioridad
- Con
Server.DisableClientPriority = truepuede restaurarse el comportamiento round-robin anterior
- Con
crypto/x509.SystemCertPoolen Windows y macOS soportaSSL_CERT_FILEySSL_CERT_DIR- Si esas variables están configuradas, lee certificados raíz desde disco y usa el verificador de Go en lugar de la API de la plataforma
- Puede desactivarse con
GODEBUG=x509sslcertoverrideplatform=0
- La implementación de HTTP/2 que antes estaba incluida en el archivo generado
h2_bundle.gode 12,226 líneas se reemplaza por el paquete realnet/http/internal/http2 - En
net/httpse agregaron hooks enchufables de HTTP/3 previos a su exposición pública, y parte de la suite de pruebas se ejecuta sobre HTTP/3- Todavía no hay una API pública invocable, pero se incluye la base para un futuro
http.Transportbasado en QUIC
- Todavía no hay una API pública invocable, pero se incluye la base para un futuro
Toolchain
go testejecuta por defecto la verificación vetstdversion, que detecta el uso de símbolos de la biblioteca estándar más nuevos que la versión de Go declarada engo.mod- Con
go doc pkg@versionse puede consultar la documentación de una versión específica de un módulo go doc -exlista ejemplos ejecutables y, si se especifica directamente el nombre de un ejemplo, imprime su fuente- A
go fixse agregan los analizadores de modernizaciónatomictypes,embedlit,slicesbackwardyunsafefuncswaitgroupcambia de nombre awaitgroupgoyfmtappendfse elimina
- En módulos Go 1.27 o posteriores,
go mod tidycombina bloquesrequiredispersos en dos bloques para dependencias directas e indirectas, preservando comentarios go tool trace -http=:6060, cuando solo recibe un puerto, se enlaza únicamente a localhost; para acceso externo debe indicarse una dirección- El comando
goelimina el soporte para el sistema de control de versiones Bazaar (bzr) compile,link,asm,cgo,coverypacksoportan archivos de respuesta (@file) al estilo GCC para evitar límites de longitud de la línea de comandos
Unicode y límites de seguridad
- Los datos Unicode de la biblioteca estándar se actualizan de Unicode 15 a Unicode 17
- Los caracteres agregados en Unicode 16 también se clasifican correctamente como símbolos y caracteres imprimibles
- Se corrige un problema que permitía escapar fuera de la raíz usando
os.Root.ReadDiryReaddir - Se vuelve más difícil el uso no autorizado de
//go:linkname- La directiva
linknamestdmarca linknames que solo puede importar la biblioteca estándar - Como el linker también verifica el acceso mediante linkname a símbolos de ensamblador, el código que depende de símbolos internos no oficiales debe probarse con anticipación
- La directiva
1 comentarios
Opiniones en Lobste.rs
Quizás sea el mejor release de la historia. Por fin llegan SIMD, uuid, jsonv2
Aunque se sale un poco del tema, es un buen ejemplo de cómo aparecen bugs cuando se trata todo como string y no se considera el contrato ni la relación entre métodos de una interfaz
Equalignora mayúsculas y minúsculas, peroHashusa el valor convertido a minúsculas. Sin embargo,EqualFoldyToLowerno definen la misma relación de equivalenciahttps://github.com/golang/go/issues/52204
"\u017F"(ſ, s larga) y"s"son iguales segúnEqualFold, pero los resultados de aplicarToLowera cada uno son distintos. Por lo tanto, si insertas"s"y luego"ſ", el hash es distinto y se inserta como una entrada separadaLo más interesante es que la documentación advierte justamente sobre este caso
https://github.com/golang/go/…
https://github.com/golang/go/…
Me alegra que otra persona haya retomado desde donde Anton se quedó
Me gusta Go, pero me pregunto si la sintaxis de Go es lo suficientemente elegante como para seguir agregando este tipo de funciones en cada release
func (b Box[T]) Map[U any](f func(T) U) Box[U] {En cambio, la verbosidad de Go y Zig tiene la ventaja de que no hace falta desplazarse a otro lugar para encontrar la definición del receptor. En el punto de llamada, que podría considerarse más importante que la definición, todos se ven casi iguales y tampoco hace falta especificar el tipo
Estuve alejado de Go por un tiempo y jsonv2 me entusiasma. Pero si pasa a ser el valor predeterminado, me pregunto si no rompe la promesa de compatibilidad que Go mantuvo durante tanto tiempo
encoding/json/v2, así que hay que elegirlo explícitamente. Elencoding/jsonexistente usa v2 internamente, pero garantiza el comportamiento anterior; además, jsonv2 incluye flags para reproducir comportamientos excepcionales de v1, por lo que no rompe la promesa de compatibilidad