<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Paulo H. R. Pinheiro</title>
    <description>The latest articles on DEV Community by Paulo H. R. Pinheiro (@paulohrpinheiro).</description>
    <link>https://dev.to/paulohrpinheiro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1357%2Fdccf8306-1623-41c0-b94d-702106d4f06d.png</url>
      <title>DEV Community: Paulo H. R. Pinheiro</title>
      <link>https://dev.to/paulohrpinheiro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paulohrpinheiro"/>
    <language>en</language>
    <item>
      <title>Arte generativa com fórmula simples em Go</title>
      <dc:creator>Paulo H. R. Pinheiro</dc:creator>
      <pubDate>Tue, 09 Jan 2024 01:26:02 +0000</pubDate>
      <link>https://dev.to/paulohrpinheiro/arte-generativa-com-formula-simples-em-go-162f</link>
      <guid>https://dev.to/paulohrpinheiro/arte-generativa-com-formula-simples-em-go-162f</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZG-YGYqv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wytutomidyjzcripmc3m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZG-YGYqv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wytutomidyjzcripmc3m.jpg" alt="Imagem pichada em Campinas" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspiração
&lt;/h3&gt;

&lt;p&gt;Essa imagem, que me persegue por várias ruas do Centro de Campinas, me faz pensar em alguma forma de desenhar através de um programa.Em outros momentos já vinha testando alguma coisa:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://paulohrpinheiro.xyz/texts/go/2019-02-18-gerando-imagens-em-go-com-biblioteca-padrao.html"&gt;https://paulohrpinheiro.xyz/texts/go/2019-02-18-gerando-imagens-em-go-com-biblioteca-padrao.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/paulohrpinheiro/generative-art"&gt;https://github.com/paulohrpinheiro/generative-art&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Explorando essa fórmula, da maneira que costumo, cheguei a uma redução bem interessante:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C + C * X * Y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Em que &lt;code&gt;C&lt;/code&gt; é uma constante qualquer, e o par &lt;code&gt;X&lt;/code&gt;, &lt;code&gt;Y&lt;/code&gt;, coordenadas da imagem gerada em um tamanho predeterminado (em geral 1000 pontos) a partir da origem &lt;code&gt;(0,0)&lt;/code&gt;. Mas o interessante é colorir essas imagens, para isso é usado resultado dessa conta módulo &lt;code&gt;M&lt;/code&gt;, em que M é o máximo de cores que se deseja usar.&lt;/p&gt;

&lt;h3&gt;
  
  
  O programa
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;PS: usei range no loop for, coisa que só está disponível na versão 1.22rc1, futuramente 1.22!&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    package main

    import (
        "flag"
        "image"
        "image/color/palette"
        "image/png"
        "os"
    )

    const (
        defaultImageSize = 1000
        defaultMaxColors = 150
        defaultConstant  = 10
        defaultFileName  = "formula.png"
    )

    func main() {
        fileName := flag.String("filename", defaultFileName, "filename to save image (.png)")
        imageSize := flag.Int("size", defaultImageSize, "size of image")
        constant := flag.Int("constant", defaultConstant, "constant for formula (c): c-c*x*y")
        maxColors := flag.Int("colors", len(palette.WebSafe), "number of colors")

        flag.Parse()

        rect := image.Rect(0, 0, *imageSize, *imageSize)
        img := image.NewPaletted(rect, palette.WebSafe)

        for x := range *imageSize {
            for y := range *imageSize {
                value := (*constant - *constant*x*y)
                color := uint8(value % *maxColors)

                img.SetColorIndex(x, y, color)
            }
        }

        f, err := os.Create(*fileName)
        if err != nil {
            panic(err)
        }

        defer f.Close()
        png.Encode(f, img)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Duas coisas que aprendi nessa empreitada, foram o pacote &lt;code&gt;flag&lt;/code&gt; e o &lt;code&gt;image/color/palette&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ao invés de construir minha própria paleta de cores como vinha fazendo há algum tempo, agora uso a paleta &lt;code&gt;palette.WebSafe&lt;/code&gt;. Outra opção pronta é a &lt;code&gt;palette.Plan9&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://pkg.go.dev/image/color/palette"&gt;https://pkg.go.dev/image/color/palette&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O pacote flag permite uma maneira rápida (e não sofisticada) de capturar argumentos em linha de comando, como por exemplo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go run formula.go -filename formula-colors:50-constant:10-size:10.png -colors 50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Em caso de parâmetro errado:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run formula.go -nada-a-ver&lt;br&gt;
flag provided but not defined: -nada-a-ver&lt;br&gt;
Usage of /tmp/go-build942068976/b001/exe/formula:&lt;br&gt;
  -colors int&lt;br&gt;
        number of colors (default 216)&lt;br&gt;
  -constant int&lt;br&gt;
        constant for formula (c): c-c*x*y (default 10)&lt;br&gt;
  -filename string&lt;br&gt;
        filename to save image (.png) (default "formula.png")&lt;br&gt;
  -size int&lt;br&gt;
        size of image (default 1000)&lt;br&gt;
exit status 2&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Algumas imagens&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Mudando os parâmetros tem-se resultados interessantemente diferentes (ou não) :)&lt;/p&gt;

&lt;h4&gt;
  
  
  colors:100 constant:10
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9Nn-GHy4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:100-constant:10-size:10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9Nn-GHy4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:100-constant:10-size:10.png" alt="colors:100 constant:10" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  colors:216 constant:10
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oJb-ib_v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:216-constant:10-size:10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oJb-ib_v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:216-constant:10-size:10.png" alt="colors:216 constant:10" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  colors:80 constant:10
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LmzGiJ4J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:80-constant:10-size:10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LmzGiJ4J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:80-constant:10-size:10.png" alt="colors:80 constant:10" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  colors:60 constant:10
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wv_i_H7P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:60-constant:10-size:10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wv_i_H7P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:60-constant:10-size:10.png" alt="colors:60 constant:10" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  colors:90 constant:10
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XjMAWJBP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:90-constant:10-size:10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XjMAWJBP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:90-constant:10-size:10.png" alt="colors:90 constant:10" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  colors:200 constant:10
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YSOruTNQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:200-constant:10-size:10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YSOruTNQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:200-constant:10-size:10.png" alt="colors:200 constant:10" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  colors:70 constant:10
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sONPzXmX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:70-constant:10-size:10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sONPzXmX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paulohrpinheiro.xyz/texts/go/images/formula-colors:70-constant:10-size:10.png" alt="colors:70 constant:10" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>generativeart</category>
      <category>go</category>
      <category>braziliandevs</category>
      <category>programming</category>
    </item>
    <item>
      <title>Testando o novo mux no GO 1.22</title>
      <dc:creator>Paulo H. R. Pinheiro</dc:creator>
      <pubDate>Fri, 05 Jan 2024 01:32:41 +0000</pubDate>
      <link>https://dev.to/paulohrpinheiro/testando-o-novo-mux-no-go-122-3173</link>
      <guid>https://dev.to/paulohrpinheiro/testando-o-novo-mux-no-go-122-3173</guid>
      <description>&lt;h3&gt;
  
  
  Motivação
&lt;/h3&gt;

&lt;p&gt;O fato da linguagem &lt;em&gt;Go&lt;/em&gt; me lembrar muito da linguagem &lt;em&gt;C&lt;/em&gt; a tornou muito confortável para mim. Em todo o tempo em que estudo a linguagem por hobby, uma coisa me incomoda: o uso de bibliotecas de terceiros para tarefas triviais.&lt;/p&gt;

&lt;p&gt;A filosofia de &lt;em&gt;Go&lt;/em&gt; vai de encontro ao meu pensamento: quanto menos bibliotecas de terceiros eu usar, melhor. Por segurança, por comodidade, por menos coisas para me preocupar, por querer uma linguagem com o máximo de "baterias inclusas".&lt;/p&gt;

&lt;p&gt;Então sempre me deu preguiça construir &lt;em&gt;APIs&lt;/em&gt; em &lt;em&gt;Go&lt;/em&gt;, pois o mais fácil é utilizar algum &lt;em&gt;muxer&lt;/em&gt; não incluso. Isso para mim é uma tarefa básica, portanto a linguagem deveria implementar da melhor maneira. Assim, cá estou eu feliz com as promessas da versão &lt;em&gt;1.22&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Infraestrutura
&lt;/h3&gt;

&lt;p&gt;É preciso ter o compilador na versão correta: &lt;em&gt;1.22rc1&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Uso o &lt;a href="https://asdf-vm.com/"&gt;asdf&lt;/a&gt; para gerenciar as linguagens de programação que utilizo. Com ele, basta instalar indicando a versão desejada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asdf install golang 1.22rc1
asdf global golang 1.22rc1
asdf reshim golang
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lembrando que se não quiser tornar essa versão a utilizada globalmente, basta entrar na pasta que queira restringir a versão e executar o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asdf local golang 1.22rc1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A forma normalmente indicada para versões não definitivas, é utilizar o &lt;a href="https://pkg.go.dev/golang.org/dl/gotip"&gt;gotip&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go install golang.org/dl/gotip@latest
gotip download
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se utilizar o &lt;em&gt;gotip&lt;/em&gt;, em todas as situações em que dever usar o comando &lt;em&gt;go&lt;/em&gt;, substitua por &lt;em&gt;gotip&lt;/em&gt;, mantendo os parâmetros.&lt;/p&gt;

&lt;h3&gt;
  
  
  Minhas fontes
&lt;/h3&gt;

&lt;p&gt;Comecei lendo o artigo de Eli Bendersky sobre isso:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://eli.thegreenplace.net/2023/better-http-server-routing-in-go-122/"&gt;https://eli.thegreenplace.net/2023/better-http-server-routing-in-go-122/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;E, conforme lá indicado, dei uma olhada na documentação da linguagem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://pkg.go.dev/net/http@go1.22rc1#hdr-Patterns"&gt;https://pkg.go.dev/net/http@go1.22rc1#hdr-Patterns&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  O programa
&lt;/h3&gt;

&lt;p&gt;Adaptado das fontes acima, eis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
  "fmt"
  "net/http"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("GET /path/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "got path\n")
  })

  mux.HandleFunc("GET /gospel/{version}/{testament}/{book}/{chapter}/", func(w http.ResponseWriter, r *http.Request) {
    version := r.PathValue("version")
    testament := r.PathValue("testament")
    book := r.PathValue("book")
    chapter := r.PathValue("chapter")

    fmt.Fprintf(w, "handling gospel with version=%v, testament=%v, book=%v, chapter=%v\n", version, testament, book, chapter)
  })

  http.ListenAndServe("127.0.0.1:8090", mux)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba-se que ao utilizar &lt;code&gt;{book}&lt;/code&gt; na configuração do endpoint, pode-se acessar a variável na posição com &lt;code&gt;book := r.PathValue("book")&lt;/code&gt;. Além de se poder indicar qual o verbo utilizado (nesse caso &lt;code&gt;GET&lt;/code&gt;). Caso se queira vários métodos para uma &lt;em&gt;URL&lt;/em&gt;, basta omitir o verbo.&lt;/p&gt;

&lt;p&gt;Para executar, as possibilidades, conforme se instalou a nova versão de &lt;em&gt;Go&lt;/em&gt;. Pelo asdf, ou instalação direta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go run server.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou pelo &lt;em&gt;gotip&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gotip run server.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executei o programa tanto em um &lt;em&gt;Debian&lt;/em&gt;, como em um &lt;em&gt;Fedora&lt;/em&gt;. No &lt;em&gt;Fedora&lt;/em&gt; rolou de boas, mas no Debian simplesmenente não foi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl localhost:8090/gospel/almeida/new/marcos/3/
404 page not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E para o outro endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl localhost:8090/path/
404 page not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lendo os documentos acima indicados com mais atenção, descobri um parâmetro que habilita ou desabilita essa feature. COofigurando uma variável de ambiente no terminal em que o servidor é executado, tudo funciona:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export GODEBUG=httpmuxgo121=0
$ go run http_server.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou então, passando a variável na linha de execução:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl localhost:8090/path/
got path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E o outro endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl localhost:8090/gospel/almeida/new/marcos/3/
handling gospel with version=almeida, testament=new, book=marcos, chapter=3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>go</category>
      <category>mux</category>
      <category>programming</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Começando com generics em Go</title>
      <dc:creator>Paulo H. R. Pinheiro</dc:creator>
      <pubDate>Wed, 27 Dec 2023 10:12:29 +0000</pubDate>
      <link>https://dev.to/paulohrpinheiro/comecando-com-generics-em-go-2oa1</link>
      <guid>https://dev.to/paulohrpinheiro/comecando-com-generics-em-go-2oa1</guid>
      <description>&lt;h2&gt;
  
  
  Motivação
&lt;/h2&gt;

&lt;p&gt;Estava estudando algoritmos de ordenação, e implementando em Go. Achei chato fazer um código que só trabalhasse com inteiros, lembrando que &lt;em&gt;Golang&lt;/em&gt; tem &lt;em&gt;generics&lt;/em&gt;.A partir disso, muitas leituras, tentativas, até o fracasso. Implementar no algoritmo foi fácil, o problema quase incontornável foi nos testes, já que insisti em seguir o "table driven tests", para variados tipos em uma só função de teste.&lt;/p&gt;

&lt;p&gt;Retomando o desafio, pensei em uma forma mais simples de testar a mesma estrutura, para não ficar perdendo tempo com erros e detalhes diferentes do novo objetivo de aprender &lt;em&gt;generics&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Aqui segue o resultado desse experimento.&lt;/p&gt;

&lt;h2&gt;
  
  
  A tarefa
&lt;/h2&gt;

&lt;p&gt;Nessa &lt;em&gt;subtask&lt;/em&gt;, defini que trabalharia em uma função mais simples, que mantivesse o espírito do problema, mas que me permitisse estudar principalmente a forma de testar.&lt;/p&gt;

&lt;p&gt;Resolvi implementar o que chamo "método de ordenação if". Dados dois números, a função deve retorná-los ordenados (&lt;code&gt;ifsort.go&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package ifsort

import "golang.org/x/exp/constraints"

func Sort[T constraints.Ordered](a, b T) (T, T) {
    if a &amp;gt; b {
        return b, a
    }

    return a, b
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Poderíamos ter várias funções, cada qual com um tipo diferente, mas o corpo da função seria o mesmo. Essa é a uma das belezas dos generis: reutilização de código, evitando que depois do "copia e cola", algo fique diferente em alguma dessas funções clonadas.&lt;/p&gt;

&lt;p&gt;Poderia, por exemplo, usar as primitivas da linguagem para definir um tipo &lt;em&gt;interface&lt;/em&gt;, como em:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type MyGenericType interface {
    int | float64 | string
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas já que temos algo pronto :), bora lá, está completo e com mais possibilidades. O Ordered é definido como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Ordered interface {
    Integer | Float | ~string
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note que &lt;em&gt;Integer&lt;/em&gt; e &lt;em&gt;Float&lt;/em&gt; expandem para todas suas variantes. E o operador &lt;code&gt;~&lt;/code&gt; usado no tipo &lt;code&gt;string&lt;/code&gt;, significa que construções como &lt;code&gt;MyStringType&lt;/code&gt; serão contempladas. O operador &lt;code&gt;|&lt;/code&gt; indica a união de todas essas possibilidades.&lt;/p&gt;

&lt;p&gt;O mais importante, com esse tipo: garantimos que nossa função só trabalha com tipos que possam ser comparados; nesse caso concreto, precisamos garantir que tenham implementado o operador &lt;code&gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O pacote constraints nos traz vários tipos, que garantem certas propriedades:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://pkg.go.dev/golang.org/x/exp/constraints#section-documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Uma boa introdução sobre generics pode ser encontrada no próprio site da linguagem:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://go.dev/blog/intro-generics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Testando
&lt;/h2&gt;

&lt;p&gt;Óbvio que numa situação real, não precisamos testar cada tipo para cobrir o espectro do &lt;em&gt;generics&lt;/em&gt; que estivermos usando. Mas, como se tratava de um experimento, prefiro sempre escrever testes do que criar uma função main e ficar alterando e testando manualmente.&lt;/p&gt;

&lt;p&gt;Eis o arquivo de teste (&lt;code&gt;ifsort_test.go&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package ifsort

import (
    "testing"

    "github.com/stretchr/testify/assert"
    "golang.org/x/exp/constraints"
)

func runAssertEqual[T constraints.Ordered](t *testing.T, input []T, output []T) {
    a, b := Sort(input[0], input[1])
    assert.Equal(t, a, output[0])
    assert.Equal(t, b, output[1])
}

type TestIntType struct {
    input  []int
    output []int
}

func TestBubbleInt(t *testing.T) {
    for _, test := range []TestIntType{
        {[]int{1, 2}, []int{1, 2}},
        {[]int{50, -101}, []int{-101, 50}},
    } {
        runAssertEqual(t, test.input, test.output)
    }
}

func TestBubbleFloat64(t *testing.T) {
    runAssertEqual(t, []float64{22.2, 11.1}, []float64{11.1, 22.2})
}

func TestBubbleString(t *testing.T) {
    runAssertEqual(t, []string{"z", "a"}, []string{"a", "z"})
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não é uma prática recomendada, reutilização de código em um teste, e nem eu gosto muito disso, mas para o objetivo aqui, tratava-se de mais uma oportunidade para brincar com &lt;em&gt;generics&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
func runAssertEqual[T constraints.Ordered](t *testing.T, input []T, output []T) {
    a, b := Sort(input[0], input[1])
    assert.Equal(t, a, output[0])
    assert.Equal(t, b, output[1])
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mais uma vez, independente do tipo, chamamos a função de ordenação, e então verificamos o resultado. E para facilitar a leitura do código, usa-se o pacote &lt;code&gt;testify&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://github.com/stretchr/testify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Usando essa abordagem, facilita-se a execução dos testes específicos. Tarefa para o fim de ano, voltar ao problema original dos algoritmos de ordenação, que requerem uma abordagem levemente diferente, por conta dos &lt;em&gt;slices&lt;/em&gt;, que serão usados, no lugar de parâmetros individuais.&lt;/p&gt;

&lt;p&gt;Publicado originalmente em &lt;a href="https://paulohrpinheiro.xyz/texts/go/2023-12-22-comecando-com-generics-em-go.html"&gt;https://paulohrpinheiro.xyz/texts/go/2023-12-22-comecando-com-generics-em-go.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>generics</category>
      <category>programming</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
