Creando una pseudo expresión lambda en Go   casi como funcionan en C#

Creando una pseudo expresión lambda en Go casi como funcionan en C#

Uno de los features de c# que extraño de alguna forma en Go, son las expresiones lambda y los métodos extendidos, trabajando en go, encontramos un enfoque similar usando genéricos y funciones anónimas, debo decir que este enfoque me permitió entender de alguna forma como funcionaban las expresiones lambda en c# pero aplicandolo en golang.

Construyendo la función de filtrado

En principio vamos a tener una lista de Usuarios cada Usuario con tres propiedades (Cedula,Nombre,Apellido), luego sobre la lista vamos a aplicar una función Where, en donde vamos a aplicar el filtro por cualquiera de los campos que necesitemos.

en C# funcionaba de la siguiente forma

Usuarios.Where(x=>x.Nombre=="alex")

Para el caso de Go, procedemos a crear una función Where que reciba una lista de tipo T de cualquier tipo, y que sobre cada elemento de la lista aplique o llame una función callback anónima que haga la validación de nuestro filtro así:

func Where[T any](list []T, callback func(T) bool) []T {
    result := make([]T, 0, len(list))

    for _, item := range list {
        if callback(item) {
            result = append(result, item)
        }
    }
    return result
}

En la función anterior recibimos un slice (lista) de tipo T y por cada elemento de la lista hacemos llamado a la función llamada callback que recibe un objeto de tipo T y retorna un booleano, si el objeto cumple la condición, agrega el elemento a un slice que sera retornado por la función Where (esta función where es la que tendria internamente la librería linq en c#).

El siguiente paso es tener nuestra estructura de usuarios:

type Usuario struct {
    Cedula   string
    Nombre   string
    Apellido string
}

Creamos una lista de usuarios:

usuarios := []Usuario{
        {Cedula: "812345", Nombre: "Juan", Apellido: "Pérez"},
        {Cedula: "1234567890", Nombre: "Ana", Apellido: "Gómez"},
        {Cedula: "8014987654", Nombre: "Luis", Apellido: "Martínez"},
        {Cedula: "5678123456", Nombre: "María", Apellido: "López"},
    }

Hacemos uso de nuestra función de filtrado

resultado := Where(usuarios, func(u Usuario) bool {
        return strings.Contains(u.Cedula, "812345")
    })

En este código estamos usando una función anónima, que recibe un parámetro de tipo Usuario, y retorna un booleano, esta función es ejecutada por nuestra función Where if callback(item) y retorna verdadero si la cédula del usuario es igual al valor filtrado.

En este punto nuestra función de filtrado puede trabajar aplicando cualquier condición filtro sobre cualquier propiedad de cada elemento de la lista, Por ultimo imprimimos el resultado de la lista filtrada:

    for _, u := range resultado {
        fmt.Printf("Usuario: %s %s, Cédula: %s\n", u.Nombre, u.Apellido, u.Cedula)
    }