Cómo usar pull-iterators

Los pull-iterators se incorporaron a la biblioteca estandar de Go en la versión 1.23, y permiten extraer elementos de un iterador de forma controlada mediante funciones. Con la función iter.Pull podemos transformar una función iteradora en el par de funciones (next, done).

En Go 1.23 se ha introducido un nuevo tipo de iteradores llamados iteradores pull, que nos ofrecen un control más preciso sobre cuándo extraer elementos de una secuencia. Para entenderlos bien, primero recordemos cómo funcionan los iteradores push, que ya existían y que consisten en funciones que nos empujan los valores automáticamente.

Los iteradores push son funciones que reciben un callback y, al ejecutarse, llaman a ese callback con cada elemento de la secuencia. Por ejemplo, si tenemos un slice con los días de la semana, podemos convertirlo en un iterador push usando slices.Values. Al llamar a este iterador, se ejecuta el callback para cada elemento, y mientras el callback devuelva true, el iterador sigue enviando valores. Esto es similar a un for each en otros lenguajes como TypeScript o Java. La característica principal es que todos los elementos se empujan de golpe cuando llamamos a la función iteradora, sin que tengamos control sobre cuándo se extrae cada valor.

En cambio, los iteradores pull funcionan de manera diferente. Se construyen a partir de un iterador push, pero nos devuelven dos funciones que nos permiten controlar la extracción de elementos. Para obtener un iterador pull, usamos la función iter.Pull, a la que le pasamos un iterador push como parámetro. Esta función nos devuelve dos funciones: next y stop.

La función next es la que usamos para extraer el siguiente elemento de la secuencia. Cada vez que la llamamos, nos devuelve un par: el valor actual y un booleano que indica si ese valor es válido. Mientras el booleano sea true, significa que hay más elementos y el valor es correcto. Cuando ya no quedan elementos, next devuelve el valor cero del tipo y false. Por eso, es importante no usar el valor si el booleano es falso, ya que no representa un dato válido.

La función stop se utiliza para liberar recursos o hacer limpieza cuando ya no necesitamos seguir extrayendo elementos. Es recomendable llamarla con un defer justo después de obtener las funciones next y stop, para asegurarnos de que se ejecuta al terminar el bloque de código. No debemos llamar a next después de haber llamado a stop, porque la memoria ya habrá sido liberada.

Con este mecanismo, podemos controlar exactamente cuándo queremos sacar el siguiente elemento, lo que puede ser útil para optimizar cálculos o para manejar secuencias de forma más perezosa. Por ejemplo, podemos hacer un bucle infinito donde llamamos a next en cada iteración, y si el booleano es falso, salimos del bucle con un break. Así, extraemos los elementos uno a uno, solo cuando nos interesa.

Este enfoque es especialmente útil cuando queremos evitar procesar todos los elementos de una secuencia de golpe, y preferimos ir tirando de ellos según nuestras necesidades. Mientras no llamemos a next, el iterador se mantiene congelado y no extrae ningún valor.

En resumen, los iteradores pull en Go 1.23 nos permiten transformar un iterador push en un par de funciones que controlan la extracción y liberación de elementos, dándonos un control más fino sobre el flujo de datos en nuestras aplicaciones. Esto amplía las posibilidades para trabajar con secuencias de datos de forma eficiente y flexible.

Lista de reproducción
  1. 1
    Funciones iteradoras
    10 minutos
  2. 2
    Funciones All y Collect
    8 minutos
  3. 3
    Cómo usar pull-iterators
    7 minutos
  4. 4
    Interning en Go con unique.Make
    8 minutos