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.