<?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>Forem: midir99</title>
    <description>The latest articles on Forem by midir99 (@midir99).</description>
    <link>https://forem.com/midir99</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%2F748146%2F22584a12-fe03-48bd-9b59-4dcb56a8712d.jpeg</url>
      <title>Forem: midir99</title>
      <link>https://forem.com/midir99</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/midir99"/>
    <language>en</language>
    <item>
      <title>¡Usa gatonaranja para descargar videos o música de YouTube! 😸</title>
      <dc:creator>midir99</dc:creator>
      <pubDate>Thu, 16 Apr 2026 23:22:10 +0000</pubDate>
      <link>https://forem.com/midir99/usa-gatonaranja-para-descargar-videos-o-musica-de-youtube-519l</link>
      <guid>https://forem.com/midir99/usa-gatonaranja-para-descargar-videos-o-musica-de-youtube-519l</guid>
      <description>&lt;p&gt;&lt;strong&gt;gatonaranja&lt;/strong&gt; es un bot de Telegram para descargar videos de YouTube.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encuéntralo en Telegram: &lt;a href="https://t.me/gatonaranjabot" rel="noopener noreferrer"&gt;@gatonaranjabot&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Código fuente: &lt;a href="https://github.com/midir99/gatonaranja" rel="noopener noreferrer"&gt;github.com/midir99/gatonaranja&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Envías el enlace del video y el bot te responde con el archivo para que puedas guardarlo en tu galería o descargas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4bg615da7kom1cdu8c4v.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4bg615da7kom1cdu8c4v.gif" alt="gatonaranja demonstration" width="600" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Puedes descargar:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Videos completos&lt;/strong&gt;&lt;br&gt;
Envía el enlace del video:&lt;br&gt;
&lt;code&gt;https://www.youtube.com/watch?v=rLo-4csv288&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clips de video&lt;/strong&gt;&lt;br&gt;
Envía el enlace del video seguido de un rango de tiempo:&lt;br&gt;
&lt;code&gt;https://www.youtube.com/watch?v=rLo-4csv288 1:14-1:24&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solo audio&lt;/strong&gt;&lt;br&gt;
Envía el enlace del video seguido de la palabra audio:&lt;br&gt;
&lt;code&gt;https://www.youtube.com/watch?v=dQw4w9WgXcQ audio&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clips de audio&lt;/strong&gt;&lt;br&gt;
Envía el enlace del video seguido de un rango de tiempo y la palabra audio:&lt;br&gt;
&lt;code&gt;https://www.youtube.com/watch?v=jsp1O7dO8a8 4:31-5:21 audio&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo funciona esto?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Es simplemente código en &lt;a href="https://go.dev/" rel="noopener noreferrer"&gt;Go&lt;/a&gt; con &lt;a href="https://github.com/yt-dlp/yt-dlp" rel="noopener noreferrer"&gt;yt-dlp&lt;/a&gt; y &lt;a href="https://ffmpeg.org/" rel="noopener noreferrer"&gt;ffmpeg&lt;/a&gt;. También utiliza la &lt;a href="https://core.telegram.org/bots/api" rel="noopener noreferrer"&gt;API de bots de Telegram&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Revisa el código en &lt;a href="https://github.com/midir99/gatonaranja" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Muchas gracias a los mantenedores de esas herramientas. Son los mejores. ♥&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Te estás robando mis datos?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No, no los quiero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Por qué haces esto?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yo sé, nadie preguntó, pero lo hice porque me gusta descargar videos de YouTube para mostrárselos a mis amigos imaginarios o para molestar a mi familia enviándoles clips de audio extraños.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Puedo hostearlo yo mismo?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;¡Sí, puedes! Recomiendo alojarlo en tu computadora local y no en un VPS, ya que yt-dlp puede tener problemas cuando la IP es detectada como tráfico de centro de datos.&lt;/p&gt;

&lt;p&gt;Aun así puedes alojarlo en un VPS, pero revisa el archivo &lt;a href="https://github.com/midir99/gatonaranja/blob/main/README.md" rel="noopener noreferrer"&gt;README.md&lt;/a&gt;, especialmente la sección sobre el flag &lt;code&gt;-ytdlp-config&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notas finales&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;¡Disfrútalo! Si te gustó, por favor dame una estrella en el repositorio de GitHub :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/midir99/gatonaranja" rel="noopener noreferrer"&gt;github.com/midir99/gatonaranja&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Un bot enfocado que hace una sola cosa bien.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>go</category>
      <category>telegram</category>
      <category>youtube</category>
      <category>download</category>
    </item>
    <item>
      <title>Use gatonaranja to download YouTube videos 😺</title>
      <dc:creator>midir99</dc:creator>
      <pubDate>Thu, 09 Apr 2026 21:14:44 +0000</pubDate>
      <link>https://forem.com/midir99/use-gatonaranja-to-download-yt-videos-3l1c</link>
      <guid>https://forem.com/midir99/use-gatonaranja-to-download-yt-videos-3l1c</guid>
      <description>&lt;p&gt;&lt;strong&gt;gatonaranja&lt;/strong&gt; is a Telegram bot for downloading YouTube videos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find it on Telegram: &lt;a href="https://t.me/gatonaranjabot" rel="noopener noreferrer"&gt;@gatonaranjabot&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source code: &lt;a href="https://github.com/midir99/gatonaranja" rel="noopener noreferrer"&gt;github.com/midir99/gatonaranja&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You send the video link, and the bot replies with the video, so you can save it to your gallery or downloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4bg615da7kom1cdu8c4v.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4bg615da7kom1cdu8c4v.gif" alt="gatonaranja demonstration" width="679" height="724"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can download:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full videos&lt;/strong&gt;&lt;br&gt;
Send the video link:&lt;br&gt;
&lt;code&gt;https://www.youtube.com/watch?v=rLo-4csv288&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Video clips&lt;/strong&gt;&lt;br&gt;
Send the video link followed by a timestamp range:&lt;br&gt;
&lt;code&gt;https://www.youtube.com/watch?v=rLo-4csv288 1:14-1:24&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audio only&lt;/strong&gt;&lt;br&gt;
Send the video link followed by the word audio:&lt;br&gt;
&lt;code&gt;https://www.youtube.com/watch?v=dQw4w9WgXcQ audio&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audio clips&lt;/strong&gt;&lt;br&gt;
Send the video link followed by a timestamp range and the word audio:&lt;br&gt;
&lt;code&gt;https://www.youtube.com/watch?v=jsp1O7dO8a8 4:31-5:21 audio&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does this work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's just Go code wired to &lt;a href="https://github.com/yt-dlp/yt-dlp" rel="noopener noreferrer"&gt;yt-dlp&lt;/a&gt; and &lt;a href="https://ffmpeg.org/" rel="noopener noreferrer"&gt;ffmpeg&lt;/a&gt;. Also, the &lt;a href="https://core.telegram.org/bots/api" rel="noopener noreferrer"&gt;Telegram bot API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check the code at &lt;a href="https://github.com/midir99/gatonaranja" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Huge thanks to the maintainers of those tools. They're the best. ♥&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are you stealing my data?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No, I don't want it. Too busy for gossiping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why are you doing this?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I know, nobody asked this, but I did it because I like to download YouTube videos to show them to my imaginary friends, or to troll my family by sending weird audio clips.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I host it myself?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, you can! I recommend hosting it on your local computer, not on a VPS, because yt-dlp may have problems when the IP is detected as datacenter traffic.&lt;/p&gt;

&lt;p&gt;You can still host it on a VPS, but check the &lt;a href="https://github.com/midir99/gatonaranja/blob/main/README.md" rel="noopener noreferrer"&gt;README.md&lt;/a&gt; file, especially the section about the &lt;code&gt;-ytdlp-config&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final notes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enjoy! If you liked it, please give me a star in the GitHub repository :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/midir99/gatonaranja" rel="noopener noreferrer"&gt;github.com/midir99/gatonaranja&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Just a focused bot that does one thing well&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>go</category>
      <category>telegram</category>
      <category>ffmpeg</category>
      <category>ytdlp</category>
    </item>
    <item>
      <title>Stop writing your SQL code inside your Go source files!</title>
      <dc:creator>midir99</dc:creator>
      <pubDate>Mon, 07 Nov 2022 01:02:12 +0000</pubDate>
      <link>https://forem.com/midir99/stop-writing-your-sql-code-inside-your-go-source-files-1768</link>
      <guid>https://forem.com/midir99/stop-writing-your-sql-code-inside-your-go-source-files-1768</guid>
      <description>&lt;p&gt;You are writing Go but you need to write some SQL, so you end up writing SQL inside your Go source code, this is not a problem as long as they are short queries, but when your queries take up more lines of code they become hard to read and to modify, besides the lack of indentation and coloring of the code make it worse.&lt;/p&gt;

&lt;p&gt;So... What is the solution?&lt;/p&gt;

&lt;p&gt;Keep your SQL code as SQL and your Go code as Go (don't write SQL inside Go).&lt;/p&gt;

&lt;p&gt;For this you can use &lt;a href="https://github.com/midir99/sqload" rel="noopener noreferrer"&gt;sqload&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;File users.sql&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- query: FindUserById&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;dob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;email&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;
 &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- query: UpdateFirstNameById&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;
   &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;
 &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- query: DeleteUserById&lt;/span&gt;
&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;File main.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"embed"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/midir99/sqload"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;//go:embed users.sql&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sqlCode&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustLoadFromString&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FindUserById&lt;/span&gt;        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`query:"FindUserById"`&lt;/span&gt;
    &lt;span class="n"&gt;UpdateFirstNameById&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`query:"UpdateFirstNameById"`&lt;/span&gt;
    &lt;span class="n"&gt;DeleteUserById&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`query:"DeleteUserById"`&lt;/span&gt;
&lt;span class="p"&gt;}](&lt;/span&gt;&lt;span class="n"&gt;sqlCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"- FindUserById&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindUserById&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"- UpdateFirstNameById&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateFirstNameById&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"- DeleteUserById&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeleteUserById&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By keeping your SQL and Go separate you get the following advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better support by your IDE or code editor (because you are now handling SQL code in its own file with its .sql extension).&lt;/li&gt;
&lt;li&gt;Your DBA will be able to easily find the code of each query that your project is running.&lt;/li&gt;
&lt;li&gt;SQL reuse, simply copy the same .sql files from one project to another.&lt;/li&gt;
&lt;li&gt;Keep your Go code free of SQL queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/midir99/sqload" rel="noopener noreferrer"&gt;sqload&lt;/a&gt; is a library with 100% test coverage, free of dependencies&lt;br&gt;
from third parties and their documentation has many examples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/midir99/sqload" rel="noopener noreferrer"&gt;sqload&lt;/a&gt; is inspired by Yesql (Clojure).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/midir99/sqload" rel="noopener noreferrer"&gt;https://github.com/midir99/sqload&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pkg.go.dev/github.com/midir99/sqload" rel="noopener noreferrer"&gt;https://pkg.go.dev/github.com/midir99/sqload&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>sql</category>
    </item>
    <item>
      <title>Deja de escribir código SQL dentro de código Go, ¡la solución está aquí!</title>
      <dc:creator>midir99</dc:creator>
      <pubDate>Mon, 07 Nov 2022 00:44:53 +0000</pubDate>
      <link>https://forem.com/midir99/deja-de-escribir-codigo-sql-dentro-de-codigo-go-la-solucion-esta-aqui-5324</link>
      <guid>https://forem.com/midir99/deja-de-escribir-codigo-sql-dentro-de-codigo-go-la-solucion-esta-aqui-5324</guid>
      <description>&lt;p&gt;Estás escribiendo Go pero necesitas escribir un poco de SQL, por lo que terminas escribiendo código SQL dentro de tu código fuente Go, esto no es un problema mientras sean consultas cortas, pero cuando tus consultas ocupan más líneas de código éstas se vuelven difíciles de leer y de modificar, además la falta de indentación y coloreado del código lo hacen peor.&lt;/p&gt;

&lt;p&gt;Entonces... ¿Cuál es la solución?&lt;/p&gt;

&lt;p&gt;Mantén tu código SQL como SQL y tu código Go como Go (no escribas SQL dentro de Go).&lt;/p&gt;

&lt;p&gt;¡Para esto puedes usar &lt;a href="//pkg.go.dev/github.com/midir99/sqload"&gt;sqload&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Archivo users.sql&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- query: FindUserById&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;dob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;email&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;
 &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- query: UpdateFirstNameById&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;
   &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;
 &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- query: DeleteUserById&lt;/span&gt;
&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Archivo main.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"embed"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/midir99/sqload"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;//go:embed users.sql&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sqlCode&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustLoadFromString&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FindUserById&lt;/span&gt;        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`query:"FindUserById"`&lt;/span&gt;
    &lt;span class="n"&gt;UpdateFirstNameById&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`query:"UpdateFirstNameById"`&lt;/span&gt;
    &lt;span class="n"&gt;DeleteUserById&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`query:"DeleteUserById"`&lt;/span&gt;
&lt;span class="p"&gt;}](&lt;/span&gt;&lt;span class="n"&gt;sqlCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"- FindUserById&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindUserById&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"- UpdateFirstNameById&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateFirstNameById&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"- DeleteUserById&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeleteUserById&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manteniendo tu SQL y Go separados obtienes las siguientes ventajas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mejor soporte por parte de tu IDE o editor de código (porque ahora estás manejando código SQL en su propio archivo con su extensión .sql).&lt;/li&gt;
&lt;li&gt;Tu DBA podrá encontrar fácilmente el código de cada consulta que tu proyecto está corriendo.&lt;/li&gt;
&lt;li&gt;Reúso de SQL, simplemente copia los mismos archivos .sql de un proyecto a otro.&lt;/li&gt;
&lt;li&gt;Mantén tu código Go libre de consultas SQL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="//pkg.go.dev/github.com/midir99/sqload"&gt;sqload&lt;/a&gt; es una librería con 100% de test coverage, libre de dependencias&lt;br&gt;
de terceros y su documentación cuenta con muchos ejemplos.&lt;/p&gt;

&lt;p&gt;&lt;a href="//pkg.go.dev/github.com/midir99/sqload"&gt;sqload&lt;/a&gt; está inspirada en Yesql (Clojure).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/midir99/sqload" rel="noopener noreferrer"&gt;https://github.com/midir99/sqload&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pkg.go.dev/github.com/midir99/sqload" rel="noopener noreferrer"&gt;https://pkg.go.dev/github.com/midir99/sqload&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>sql</category>
      <category>spanish</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
