Executando verificação de segurança...
5

Melhorando os slices em golang

Melhorando os slices em golang

Eu sempre gostei de como a linguagem go é simples e como isso facilita escrever e interpretar códigos escritos nela.

Mas algumas coisas me incomodam um pouco nessa linguagem e isso inclui os arrays/slices.

A diferença entre esse dois não é muito relevante pra esse post, o pont é que eu não gosto muito da forma como essas estruturas são manipuladas em go.

Por exemplo se você quiser encontrar um item em um slice vai ter que implementar por conta própria.

O código abaixo simplesmente encontra um elemento em um slice e retorna o index dele ou -1 se o elemento não for encontrado.

func find(arr []string, v string) int {
    for i, s := range arr {
        if v == s {
            return i
        }
    }
    
    return -1
}

Esse pode ser um exemplo bobo, mas se você tiver que implementar por conta própria cada operação a ser feita em um slice isso se torna bem monótono.

Hoje em dia existe o pacote slices na biblioteca padrão, mas sendo bem sincero eu não fui muito com a cara dele, mesmo assim reconheço que ele facilitou bastante a forma como lidamos com essas estruturas de dados.

E por causa dessa minha insatisfação eu criei um package chamado arrays (tava sem criatividade pra nome) para facilitar minha vida em relação a esse problema.

O package arrays

A ideia aqui é bem simples, implementar funcionalidades semelhantes aos arrays do javascript no go. Por que? Porque eu gosto de trabalhar com os arrays do js e acho bem direto ao ponto.

Todo esse package gira em torno do tipo Array que é definido da seguinte forma:

type Array[T any] []T

Pra criar um novo tipoArray você pode usar a função New:

func New[T any](items ...T) Array[T]

Esse tipo é manipulado através de métodos ao invés de funções como no caso do package slices (com excessão da função Map).

Aqui está um código de exemplo, nele eu uso o método filter para encontrar todas as urls válidas em um Array:

package main

import (
    "fmt"
    "regexp"
    
    "github.com/w1tchCrafter/arrays"
)

func main() {
    // expressão regular para validação de url
    urlRegex := `^https?:\/\/(?:www\.)?[a-zA-Z0-9-]+(?:\.[a-zA-Z]{2,})+(?:\/[^\s]*)?$`
    
    re := regexp.MustCompile(urlRegex)
    
    urls := arrays.New(
        "https://www.example.com",
        "http://example.com",
        "https://example.com/path/to/resource",
        "ftp://invalid-url.com",
        "invalid-url",
    )
    
    valid := urls.Filter(func(_ int, u string) bool {
        return re.Match([]byte(u))
    })
    
    fmt.Println(valid) //Deve printar os 3 primeiros itens
}

Eu ainda não cheguei nem perto de dizer que finalizei esse projeto mas aqui estão algumas das funcionalidades que eu já consegui implementar:

  • ForEach
  • Len
  • Join
  • At
  • Pop
  • Push
  • Shift
  • Unshift
  • ToSlice
  • Find
  • Map
  • Filter

Eu não vou entrar em tantos detalhes aqui pro post não ficar tão grande, quem tiver interesse pode conferir aqui.

Lembrando que tudo que eu comentei aqui é minha opinião, gostaria muito de ouvir as opiniões de vocês também, e com isso eu me despeço.

Carregando publicação patrocinada...
1

Opa, também sou fan de Golang apesar de não ter tanto problema quanto aos slices. E na verdade eu tenho algumas dúvidas sobre o método Map que você pretende criar não seria melhor um ToMap para converter para o Map nativo do golang? ou tu só quer tratar os slices como map?


2

Na verdade a função Map não tem nada a ver com a estrutura de dados. Ela funciona da mesma forma que o método Array.map do javascript, onde você executa uma callback em cada elemento da array e então retorna um novo arrays com os valores de retorno desse callback.

Por exemplo, esse código pega cada número em um array e retorna um novo array com os valores dobrados:

let arr = [1, 2, 3, 4];
arr.map(n => n * 2); //[2, 4, 6, 8]

Mesmo código em go:

n := arrays.New(1, 2, 3, 4)
arrays.Map(n, func(_ int, x int) int { return x * 2 }) //[2, 4, 6, 8]
1

Ah sim, esqueci que o map do javascript era mais puxado para programação funcional

Enfim, vou dar uma brincada com o código e uma refatorada, se tu quiser entrar em contato depois tem meu discord no perfil