1 puntos por GN⁺ 2025-06-04 | 1 comentarios | Compartir por WhatsApp
  • La repetición de if err != nil en Go ha sido una gran fuente de quejas en las encuestas de usuarios durante años, pero el equipo de Go decidió no impulsar por ahora cambios de sintaxis para el manejo de errores
  • Las propuestas de 2018 check/handle, de 2019 try y de 2024 ? no lograron suficiente consenso, y en especial try recibió fuerte rechazo por su flujo de control oculto
  • Según el proceso de propuestas de Go, si no hay un consenso general, normalmente la propuesta se rechaza, y ni siquiera entre los miembros veteranos del equipo de Go en Google hay unanimidad sobre cuál es la mejor dirección en este momento
  • La postura de mantener el estado actual considera que Go ya tiene una forma de manejo de errores que funciona, y que una nueva sintaxis generaría costos importantes en estilo de código, depuración, documentación, herramientas y código existente
  • El equipo de Go cerrará sin investigación adicional las propuestas abiertas y nuevas cuyo objetivo principal sea la sintaxis de manejo de errores, y se enfocará en otras oportunidades de mejora hasta que exista una comprensión más clara del problema

La vieja queja causada por if err != nil

  • Uno de los reclamos más persistentes sobre Go es la verbosidad del código de manejo de errores
  • El patrón representativo es el siguiente
x, err := call()
if err != nil {
    // handle err
}
  • En programas con muchas llamadas a APIs y donde el error simplemente se devuelve, if err != nil puede terminar dominando el resto del código
  • En la función de ejemplo printSum, de las 10 líneas del cuerpo de la función, 4 parecen trabajo real —incluyendo llamada, impresión y retorno— y las otras 6 parecen ruido
  • En la encuesta anual de usuarios de Go, el manejo de errores ha sido durante años una de las principales quejas; por un tiempo la falta de genéricos la superó, pero desde que Go añadió genéricos, el manejo de errores volvió a ocupar el primer lugar

Tres propuestas sintácticas importantes

  • El primer intento explícito del equipo de Go comenzó en 2018 como parte del esfuerzo de Go 2, cuando Russ Cox resumió formalmente el problema
  • El borrador de diseño de Marcel van Lohuizen se basaba en los mecanismos check y handle, e incluía análisis de enfoques de otros lenguajes y alternativas
func printSum(a, b string) error {
    handle err { return err }
    x := check strconv.Atoi(a)
    y := check strconv.Atoi(b)
    fmt.Println("result:", x + y)
    return nil
}
  • El enfoque check/handle se consideró demasiado complejo, y en 2019 apareció una propuesta más simple de try
    • La palabra clave similar a check pasó a ser la función integrada try
    • La parte de handle se eliminó
    • Se creó la herramienta tryhard para convertir código existente de manejo de errores al estilo try
    • El issue de GitHub relacionado se debatió intensamente con casi 900 comentarios
func printSum(a, b string) error {
    // use a defer statement to augment errors before returning
    x := try(strconv.Atoi(a))
    y := try(strconv.Atoi(b))
    fmt.Println("result:", x + y)
    return nil
}
  • try afectaba el flujo de control al hacer que, cuando había un error, se devolviera desde la función contenedora, y como ese retorno podía ocurrir incluso dentro de expresiones profundamente anidadas, a muchos usuarios les resultó difícil de aceptar
  • En ese momento quizá habría sido mejor introducir una nueva palabra clave; hoy además se puede controlar con precisión la versión del lenguaje mediante el archivo go.mod y directivas por archivo
  • La propuesta reciente de Jimmy Frasche vuelve al diseño original de check/handle intentando resolver algunas de sus desventajas

Reflexión sobre el proceso después de try y la propuesta de ?

  • Después de la propuesta try, Russ Cox revisó el proceso de propuestas en su serie “Thinking about the Go Proposal Process”
  • “Go Proposal Process: Large Changes” evalúa que try debió haber sido un segundo borrador de diseño y no una propuesta con calendario de implementación
  • En los años siguientes, el equipo de Go no impulsó cambios sintácticos para el manejo de errores, mientras en la comunidad siguieron llegando propuestas parecidas, interesantes, difíciles de entender o inviables
  • Ian Lance Taylor creó un umbrella issue para resumir el estado de las propuestas de mejora del manejo de errores, y también surgió una Go Wiki para reunir comentarios y discusión relacionados
  • “go error handling proposals” de Sean K. H. Liao sigue muchas de las propuestas de manejo de errores a lo largo de varios años
  • Como el descontento continuó, Ian Lance Taylor presentó en 2024 una propuesta para reducir el boilerplate del manejo de errores usando ?
    • La notación estaba tomada del operador ? de Rust
    • En un pequeño estudio informal con usuarios, la mayoría de los participantes dedujo correctamente el significado del código Go usando ?
    • También se hicieron una herramienta para convertir código Go general a la nueva sintaxis y un prototipo del compilador
func printSum(a, b string) error {
    x := strconv.Atoi(a) ?
    y := strconv.Atoi(b) ?
    fmt.Println("result:", x + y)
    return nil
}
  • Esta propuesta también se llenó rápidamente de muchos comentarios y sugerencias de ajustes basadas en preferencias, e Ian cerró la propuesta y movió el contenido a una discusión
  • Una versión ligeramente ajustada recibió una reacción algo más positiva, pero no obtuvo apoyo amplio

Por qué quieren pausar esto por ahora

  • El equipo de Go considera que, en el futuro previsible, debe dejar de intentar resolver el problema sintáctico del manejo de errores
  • El proceso de propuestas respalda esta decisión
    • El objetivo del proceso de propuestas es alcanzar a tiempo un consenso general sobre el resultado
    • Si no se encuentra consenso general en la discusión del issue tracker, la propuesta normalmente se rechaza
    • Si no se encuentra consenso ni un siguiente paso, los arquitectos de Go revisan la discusión e intentan lograr un acuerdo interno
  • Ninguna propuesta de manejo de errores consiguió apoyo cercano al consenso, y todas fueron rechazadas
  • Ni siquiera los miembros veteranos del equipo de Go en Google están unánimemente de acuerdo sobre cuál es la mejor forma de avanzar, y sin un acuerdo fuerte no es razonable seguir adelante

Los argumentos a favor del estado actual y del cambio

  • Del lado de mantener el estado actual hay razones prácticas relacionadas con la madurez de Go y el costo para el ecosistema
    • Si Go hubiera introducido desde el principio azúcar sintáctica específica para manejo de errores, hoy probablemente habría menos discusión, pero Go ya tiene 15 años y ya cuenta con una forma de manejo de errores que funciona
    • Incluso si ahora se encontrara una solución perfecta, la situación podría simplemente cambiar para que quienes queden insatisfechos sean los partidarios del estado actual en vez de quienes impulsan el cambio
    • Los genéricos no necesitan ser usados directamente por todos los usuarios, pero una nueva sintaxis de manejo de errores podría hacer que, si no se usa, el código se vea poco idiomático, por lo que en la práctica casi todos tendrían que adoptarla
    • Añadir nueva sintaxis también podría chocar con la regla de diseño de Go de no ofrecer varias formas de hacer lo mismo
  • La capacidad de redeclaración en la declaración corta de variables := se introdujo para resolver problemas surgidos por el manejo de errores
    • Sin redeclaración, cada comprobación de error consecutiva habría requerido nombres err distintos o declaraciones de variables separadas
    • Si en ese momento hubiera existido un mejor soporte sintáctico para el manejo de errores, quizá no habría sido necesaria la regla de redeclaración ni su complejidad asociada
  • Cuando los errores se enriquecen y manejan correctamente, la proporción de repetición simple disminuye
    • En las encuestas de usuarios aparece repetidamente el comentario de que los errores no tienen stack traces
    • Es posible usar funciones auxiliares para crear y devolver errores enriquecidos
    • Si se agrega información de entrada, como en fmt.Errorf("invalid integer: %q", a), el peso relativo del boilerplate se reduce
  • La biblioteca estándar también puede reducir el boilerplate del manejo de errores
    • Va en la línea de “Errors are values” de Rob Pike
    • En algunos casos, cmp.Or puede usarse para manejar varios errores a la vez
  • Escribir, leer y depurar son actividades distintas
    • Escribir comprobaciones repetitivas de errores es tedioso, pero el autocompletado asistido por IDE y LLM puede generar fácilmente el manejo de errores básico
    • Al leer, la verbosidad se nota más, y los IDE podrían ofrecer un toggle para ocultar el código de manejo de errores
    • Al depurar, tener un if separado ya facilita agregar println o poner breakpoints
    • Si el manejo de errores queda oculto detrás de check, try o ?, normalmente podría ser necesario volver a expandirlo a un if, y ese proceso puede complicar la depuración o introducir bugs sutiles
  • Un cambio en el lenguaje trae costos no solo de diseño e implementación, sino también de modificar código existente, actualizar documentación y ajustar herramientas
    • El equipo de Go es relativamente pequeño y tiene muchas otras prioridades que atender
    • Las prioridades y el tamaño del equipo pueden cambiar
  • Algunos usuarios de Go con los que habló el equipo en Google Cloud Next 2025 dijeron con fuerza que el lenguaje no debería cambiarse por un mejor manejo de errores
    • Dijeron que, al llegar desde otros lenguajes, la falta de sintaxis dedicada para el manejo de errores en Go es lo que más llama la atención, pero que se vuelve menos importante cuando empiezan a escribir código Go más idiomático
    • Esta muestra no es lo bastante grande como para ser representativa, pero puede pertenecer a un grupo distinto al de quienes se ven en GitHub
  • Los argumentos a favor del cambio siguen siendo válidos
    • La falta de un mejor soporte para el manejo de errores sigue siendo la principal queja en las encuestas de usuarios
    • Un enfoque centrado solo en reducir caracteres puede ser la dirección equivocada
    • Si el manejo básico de errores se hace más visible con una palabra clave y a la vez se elimina el boilerplate de err != nil, en revisión de código podría ser más fácil verificar si el manejo de errores está presente
    • Aún no se sabe suficientemente si el núcleo del problema es solo la verbosidad sintáctica o la verbosidad del buen manejo de errores al construir errores significativos para APIs, desarrolladores y usuarios finales

La decisión del equipo de Go

  • Hasta ahora, ningún intento de abordar el manejo de errores ha conseguido suficiente impulso
  • El equipo de Go considera que falta una comprensión compartida del problema, e incluso no todos están de acuerdo en que realmente exista un problema
  • En el futuro previsible no impulsará cambios sintácticos en el lenguaje para el manejo de errores
  • Las propuestas abiertas y las futuras propuestas cuyo objetivo principal sea la sintaxis de manejo de errores se cerrarán sin investigación adicional
  • La exploración y discusión de la comunidad no terminó en cambios sintácticos para el manejo de errores, pero sí llevó a varias mejoras del lenguaje Go y de su proceso

1 comentarios

 
GN⁺ 2025-06-04
Comentarios de Hacker News
  • Si el equipo de Go quiere que la gente deje comentarios ligeros del tipo “si hubieran hecho esto, ya estaría resuelto”, primero estaría bien que vieran la página wiki enlazada en el artículo https://go.dev/wiki/Go2ErrorHandlingFeedback y la búsqueda de issues en GitHub https://github.com/golang/go/issues?q=+is%3Aissue+label%3Aerror-handling
    Casi seguro que lo que están por proponer no es algo nuevo, y es muy probable que muchas de esas ideas ya se hayan revisado a fondo
    Me gusta este enfoque tan honesto del equipo de Go, y todavía disfruto usar Go todos los días en el trabajo

    • En el borrador de diseño que sirvió de base para la retroalimentación aparecen C++, Rust y Swift, pero en el enorme documento de comentarios enlazado no encontré enfoques como la notación do, las for-comprehensions o el monadic-let que se usan en Haskell/Scala/OCaml
      Tampoco vi nada parecido en varias páginas de los issues de GitHub con más comentarios, y sería demasiado asumir que, como el equipo de Go son magos del diseño de lenguajes, necesariamente ya revisaron las soluciones que la gente aquí menciona a la ligera
      El equipo de Go cometió el mismo error que Java, es decir, tener tipado estático sin polimorfismo paramétrico, y la raíz de este problema de manejo de errores está ahí, pero da la impresión de que no quieren reconocerlo y corregirlo
    • Me sorprende que gente realmente inteligente y con mucha experiencia haya escrito esa página y discutido el tema durante años, y aun así no aparezca por ningún lado la solución al estilo Haskell de usar los mónadas Maybe/Either y la notación do con la operación bind
      Puede sonar grandilocuente o intimidante, pero es una forma elegante y funcionalmente pura de propagar errores hasta donde puedan manejarse sin que se olviden
      Para quienes escriben código en Haskell es un enfoque tan arraigado que cuesta entender que no hubiera nadie en la comunidad de Go que lo conociera y le gustara
      Agradezco la página y los enlaces, pero resulta confuso que personas tan atentas a su lenguaje hayan pasado por alto una solución tan bien establecida
    • Seguro que ya hay una respuesta por ahí, pero me da curiosidad por qué esto es un problema especialmente difícil solo en Go
      Casi todos los lenguajes parecen tener una manera mejor de hacerlo, así que quisiera saber si simplemente no logran decidirse o no pueden dejar a todos contentos, o si hay una razón concreta por la que las soluciones de otros lenguajes no encajan en Go
    • Un patrón que se ve mucho en las críticas a Go es que personas relativamente amateurs asumen que quienes crean Go saben menos de lenguajes de programación que ellas
      En realidad, en casi todos los casos saben muchísimo más
      El amateur piensa ingenuamente que el mejor lenguaje es el que mete la mayor cantidad posible de funciones, y más todavía si incluye las que a él le gustan
      Es como alguien que apenas empieza a fabricar cuchillos, ve un cuchillo de chef japonés y lo siente insuficiente, y luego piensa que sería mejor si le añadiera un mango impreso en 3D con ranuras para los dedos, un compartimento secreto, un encendedor y un altavoz Bluetooth
    • Es raro que todavía le llamen Wiki cuando ahora hay que pedir aprobación para editarla
  • Solo hay que hacer una lista de verificación, discutir y completar cada punto, y luego no quitarlo otra vez salvo que se descubra un error semántico fatal o un hueco de solidez
    Cuando todo esté completo, se implementa, y la gente que discutía si debía escribirse .await, /await o .await!() vuelve a desaparecer
    Rust funciona así; algunos temas se retrasan más de 10 años, pero al final los puntos se completan y se estabilizan en la nightly más reciente
    Si Go no puede resolver un único problema con el que todos chocan de inmediato, aun teniendo varias propuestas bastante pulidas, solo porque no logra elegir una y está esperando a que termine el bikeshedding, entonces ese proceso es una comedia

    • No existe algo como “varias propuestas perfectas y terminadas”
    • Así es exactamente como Rust se ganó la reputación de ser un lenguaje feo de leer y con una sintaxis inconsistente debido al diseño por comité
    • Un lenguaje de programación es un sistema diseñado, así que debe tener sentido como un todo
      No es una colección de funciones que se agregan solo por cumplir requisitos de una lista de verificación
    • Quiero poner un recordatorio para dentro de 25 años
      ¿Rust se habrá convertido en un desastre como C++? ¿Go seguirá siendo un lenguaje atemporal como lo era cuando salió?
    • Eso de que “Go no puede resolver un único problema que todos enfrentan de inmediato” suena raro
      En la encuesta, el manejo de errores fue mencionado por el 13%, y también hay personas que prefieren dejarlo tal como está ahora
      https://go.dev/blog/survey2024-h1-results
  • Alguna vez escribí una función de Go poco común donde esperaba que una función interna devolviera un error
    Así que, si la función interna no devolvía un error, la función externa tenía que devolver un error y hacer otro procesamiento; y si la función interna devolvía un error, tenía que devolver nil
    En resumen, en vez de if err != nil { ... } tenía que usar if err == nil { // return an error }, pero por costumbre escribí lo primero y me tomó bastante tiempo depurarlo
    Fue porque me volví tan insensible a if err != nil que mi cerebro ni siquiera consideró la posibilidad de que esa construcción no debía estar ahí
    Por eso creo que las expresiones comunes necesitan azúcar sintáctico. Si la diferencia entre el extremadamente común if err != nil y el poco frecuente if err == nil hubiera resaltado más, realmente habría ayudado

    • Cada vez que uso if err == nil, le pongo el comentario // inverted para que destaque
      Estaría bien que se manejara a nivel del lenguaje, pero al menos comparto una forma de hacerlo más visible
    • Claro, if fruit != "Apple" { ... } también puede crear exactamente la misma situación
      Me pregunto si existe una solución general para mejorar esto, y parece un poco errado verlo como un problema exclusivo del manejo de errores
      No hay nada especial ni único en los errores; son solo un estado como cualquier otro
    • Esto más bien se convierte en un argumento en contra de cambiar la sintaxis
      Si aparece un patrón común como if err == nil { return ... }, entonces ahora eso también quedaría esparcido por todo el código
      La solución actual está bien, y parece que a quienes más les disgusta es a quienes recién empiezan con Go o son principiantes
      A mi alrededor, a la gente le gusta el manejo de errores “verboso” porque es explícito, claro y fácil de leer
    • Haciendo de abogado del diablo, el IDE y la fuente podrían, solo en el modo de sintaxis de Go, resaltar if err != nil como si fuera un único símbolo de ligadura pequeño o renderizarlo atenuado en el fondo
      Entonces cualquier forma distinta de esa cadena exacta, como if err == nil, destacaría más
    • Buen punto. Parece que también podría resolverse en el editor con una notación plegada como if err … {
  • Me gusta el manejo explícito de errores de Go
    Una función siempre tiene éxito, o puede tener éxito o fallar. Las funciones que siempre tienen éxito son simples, y si una función que puede fallar falla, el código externo no puede continuar en estado de fallo, así que debe manejarlo
    Aquí es donde los lenguajes se separan. Muchos lenguajes lanzan excepciones, las van propagando hasta que alguien las atrapa explícitamente y proporcionan algún tipo de stack trace
    En Go me gusta que, al escribir código, siempre hay una decisión que tomar: ignorar el error y seguir (foo, _ := doSomething()), regresar temprano sin información útil (return nil, err), regresar temprano agregando contexto útil, o interpretar el error recibido y bifurcar a partir de eso
    Por ejemplo, si no se encuentra la fila a modificar en la base de datos, la capa de servicio puede devolver un error de not found y en la API eso se convierte en 404, o una función de borrado idempotente puede interpretar not found como éxito
    En Go 2 o en otro lenguaje, estaría bien tener un tipo Result al estilo Rust/Swift en vez de tuplas nulables, y tipos de error mejor tipados y enumerables en vez de usar siempre error directamente
    Pero si se agregara Result encima del retorno idiomático de tuplas de Go 1, habría varias formas de hacer lo mismo y eso generaría confusión y fragmentación, así que encaja mejor en Go 2 o en un lenguaje nuevo

    • Por mi experiencia, la política de manejo de errores debería delegarse en quien llama
      Las capas bajas del stack por lo general no saben qué hacer, así que no deberían manejar el error
      La política de “manejar” errores suele terminar siendo una política de envolverlos y devolverlos de nuevo hacia arriba en el stack, y eso se vuelve bastante trabajo rutinario
    • “Si una función falla, debes manejar ese fallo” es precisamente donde Go falla
      Go permite ignorar por completo los errores, y como resultado eso puede terminar en crashes
      No termino de entender cómo se puede identificar correctamente lo que se necesita para construir software robusto y aun así gustar del manejo de errores de Go
    • Ojalá que la sintaxis de borgo[1] se convirtiera tal cual en el lenguaje Go 2. Soñar no cuesta nada
      [1]: https://borgo-lang.github.io/ | https://github.com/borgo-lang/borgo
    • A este ritmo, Go2 parece un laboratorio de ideas que nunca va a salir
    • Me gustaría preguntar: ¿mejor en comparación con qué?
      Todos los lenguajes funcionales, muchos lenguajes modernos como Rust, e incluso Java con checked exceptions ofrecen esto
      En cualquier lenguaje con genéricos probablemente se puede replicar en gran medida el “manejo de errores” al estilo Go, y seguramente saldría mejor código
      Si la respuesta es JavaScript o Python, bueno, ese sí es un patrón de comparación común
  • Para Go esta es la decisión correcta. Cuando conocí Go al principio no me gustaba el manejo de errores, pero ahora realmente me gusta
    Hubo dos cosas que me hicieron cambiar. Leí https://go.dev/blog/errors-are-values y adopté de verdad la perspectiva de que “los errores son valores”, y sobre esa base incluso hice el paquete algo popular https://github.com/stytchauth/sqx
    Además, me fui acostumbrando a usar un poco panic(err) para estados realmente absurdos e inválidos
    No hay por qué obligar al código padre a manejar a la fuerza estados absurdos que ni siquiera tendría criterio para resolver, y con uno o dos panic bien puestos puedes eliminar cientos de verificaciones de error en una base de código
    Por ejemplo, se puede pensar en algo como si existe un logger predeterminado dentro de ctx

    • Es una lástima. Ninguno de los dos argumentos que diste tiene que ver con lo malo que es el manejo de errores de Go, y tampoco haría daño mejorarlo
      Más bien, es muy probable que mejorara
    • Incluso PHP tiene un mejor manejo de errores gracias a los niveles de error y al operador @ para suprimir errores en el punto de llamada
      bash también tiene -e
    • A mí también me gusta el enfoque de Go. Si eso me da más certeza de lo que está pasando, acepto tener más líneas de código
      Antes, cuando empecé a usar C#, pensaba que entender el flujo de try/catch/finally, using, el anidamiento, qué pasa si hay un error en el catch y qué pasa si lo hay en el finally era algo inteligente
      Ahora prefiero no tener que pensar en esas cosas
    • Los errores de tipo suma al estilo Rust también son valores
  • No me gusta la forma en que este texto dice que el problema principal del manejo de errores en Go es que la sintaxis es demasiado verbosa. Eso no me preocupa mucho
    Lo más importante es que los errores pueden descartarse silenciosamente o ignorarse por accidente, y que el resultado de una llamada de función no es un valor que se pueda guardar o pasar fácilmente; además, se necesita errors.Is, y todo el tema de los errores “anidados” es un mecanismo raro en tiempo de ejecución que no encaja bien con el sistema de tipos
    También es difícil hacer switch sobre errores, la biblioteca estándar usa valores centinela, y la interacción con los genéricos no es buena, así que terminan haciendo falta paquetes como errgroup
    ¿Se me está escapando algo más?

    • El 90% del tiempo que paso trabajando profesionalmente con Go es inventar casos de prueba a la fuerza para cubrir con cobertura de sentencias cada rama de retorno de error
      Si fuera un lenguaje con excepciones, nadie haría eso
    • No veo que en ningún lugar de este texto se afirme que “el problema principal es que la sintaxis es demasiado verbosa”
      Han decidido no seguir intentando cambiar la sintaxis del manejo de errores en el futuro previsible, y gracias a eso ahora hay atención disponible para revisar otros problemas, ya sean de errores o de otros temas
    • Hay que recordar que incluso para que Go soportara alguna forma de genéricos se tardó una enormidad
      La evolución de Go es glacial, y para mucha gente eso no es un bug sino una feature
    • 100% de acuerdo. Los dos son Googlers, así que da mucha pena volver a decepcionarse del equipo de Go
    • Estoy de acuerdo con el punto 1, pero se puede mitigar en cierta medida con herramientas de desarrollo como errcheck: https://github.com/kisielk/errcheck?tab=readme-ov-file
  • Da risa la explicación de que “las opiniones de la encuesta que dicen que los errores no tienen stack trace se pueden resolver haciendo que una función auxiliar cree y devuelva un error enriquecido”
    Es curioso llamar “manejo de errores” a proporcionar manualmente el stack trace con algo como if err != nil { return fmt.Errorf("invalid integer: %q", a) }
    Según la definición del equipo de Go, las excepciones entonces manejan los errores automáticamente. Claro, en los lenguajes que no son C++

    • Da risa que la gente vea stack traces que llenan toda la pantalla y diga que son claros y útiles
      Puede ser, pero ¿de verdad hace falta todo eso? ¿Y qué hay del costo del logging?
      Creo que un error envuelto de una sola línea que recorte el ruido del framework y del runtime es mucho mejor
      Si se envuelve bien, además es muy fácil de buscar, y normalmente se puede rastrear con más eficacia que con un stack trace
      Llevo más de 10 años usando Go full-time y nunca he necesitado el ruido verboso de las funciones del runtime o de la pila de llamadas
  • Desde la perspectiva de un desarrollador de Elixir, esto parece una locura
    En Erlang/Elixir normalmente se resuelve haciendo que las funciones devuelvan tuplas {:ok, result} o {:error, description_or_struct}
    Si además usas la sentencia with de Elixir, puedes concentrar el manejo de errores al final y queda mucho más legible
    Go podría agregar algo equivalente a una cláusula with para seguir encadenando funciones mientras el error sea nil, y dejar abajo una cláusula de manejo de errores

    • Viendo solo la evidencia disponible, no parece que Go tenga ninguna posibilidad de adoptar una sentencia with
      Es interesante cómo Go retrasa durante muchísimo tiempo estructuras básicas y obviamente valiosas como genéricos, manejo de errores y gestión de paquetes por falta de consenso en la comunidad
      Los genéricos tardaron 13 años desde la publicación como open source; 16 años después todavía no hay manejo de errores; y la gestión de paquetes tardó unos 9 años
      Pensarlo bien tiene valor, pero lanzar cosas también lo tiene. La gente que escribe 900 comentarios en GitHub igual va a seguir usando Go, y muy probablemente habría sido mejor que el lenguaje incorporara algo en vez de seguir posponiéndolo
    • El retorno múltiple de Go en sí mismo me parece raro
      Con una función que tiene varios tipos de retorno no puedes hacer mucho más que asignarla a variables
    • Los usuarios de Haskell y los fans de Rust se adueñan de los tipos suma como si fueran suyos, y a la gente le termina dando rechazo porque leen sus comentarios y textos y no quieren caer por esa aterradora madriguera de conejo de Hindley-Milner
      Pero en Erlang y Elixir es una forma totalmente idiomática y sin carga extra
      De hecho, en cierto sentido es incluso más potente que en la familia ML, porque allí sus tipos suma son abiertos
  • No he seguido esta discusión en detalle, pero no entiendo por qué no adoptan simplemente el enfoque estilo Rust
    Esa también es la forma que yo agregué de inmediato a Go después de que tuvo genéricos
    En el artículo enlazado solo veo la explicación de que “Rust no tiene algo equivalente a handle, y la conveniencia del operador ? puede hacer que se omita un manejo adecuado”
    Pero no entiendo por qué que algo sea conveniente significaría ignorar errores
    La mitad del problema del enfoque de Go es que no obliga a hacer nada con el resultado y solo obliga mínimamente a revisar errores
    x, err := strconv.Atoi("123"); fmt.Println("result:", x) da declared and not used: err, pero después de una segunda conversión puede ejecutarse sin problema aunque no revises err, porque el valor por defecto de y, que es 0, puede ocultar el problema
    Incluso si dejas vacío algo como if err != nil { }, compila y se ejecuta, y no hay forma de saber que algo salió mal
    Si el valor de retorno fuera un Result, se obligaría a tomar una decisión. Aunque alguien abuse de ! o simplemente propague cómodamente con ? sin manejar el caso de error, entonces ¿también van a prohibir panic?

    • Go no tiene tipos suma, así que no puede tener Result
      Y por esa extraña obsesión con que todos los tipos deban tener un valor cero definido, tampoco pueden agregar tipos suma
    • Entiendo que quieren decir que, si ? es cómodo de usar, nadie volverá a envolver errores
      Es una lógica muy dudosa
      Para empezar, podrían diseñar ? de forma que fomente envolver errores
    • Porque no está claro cuál sería exactamente la forma equivalente al meter el estilo Rust en Go
      Por ejemplo, ¿qué aspecto debería tener en Go algo equivalente a From de Rust?
    • ? tiene poca visibilidad y esconde una bifurcación del flujo de control dentro de una sola sentencia o expresión
      Esa es también una de las razones por las que Go eliminó el operador ternario y prefirió una sentencia if con cada rama en una línea separada
      Tampoco es fácil poner puntos de interrupción, y hace más probable preferir propagar el error tal cual en vez de enriquecerlo o manejarlo
    • Pensaba que := era una declaración y asignación de una sola sentencia, pero en la línea 5 del ejemplo, ¿no se está redeclarando err y no queda el nuevo err ocultando al err anterior?
      Si es así, parecería que debería fallar con declared and not used: err, porque la nueva variable err no se usó
      ¿O si la variable ya existe, := simplemente funciona como una asignación normal?
  • Decir que “el hecho de que los errores no tengan rastreo de pila puede resolverse haciendo que una función auxiliar cree y devuelva un error enriquecido” es ser demasiado optimista sobre la realidad
    Los lenguajes con rastreo de pila te lo dan gratis, pero en Go hay que implementarlo cada vez
    Uno puede ser un desarrollador disciplinado que siempre adjunta detalles, pero no todos los miembros del equipo van a tener esa misma disciplina
    Lo mejor del rastreo de pila es que te da la ruta de llamadas hasta el error
    Si ocurre un error en un método llamado desde varios lugares, con el rastreo de pila puedes ver de inmediato qué ruta se tomó
    Durante muchos años hice trabajo parecido a sysadmin/SRE y resolví muchos problemas; cuando había rastreo de pila, los problemas fáciles se resolvían en 1 o 2 minutos porque la causa era obvia
    En Go, si alguien no enriquece el error o reutiliza el mismo mensaje de error, hasta un problema fácil se vuelve un trabajo de deducción y toma más tiempo