<?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: Nikita Galushko</title>
    <description>The latest articles on DEV Community by Nikita Galushko (@nikgalushko).</description>
    <link>https://dev.to/nikgalushko</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%2F449457%2F3e191608-4504-43d2-a082-73f4f0c30cdf.jpg</url>
      <title>DEV Community: Nikita Galushko</title>
      <link>https://dev.to/nikgalushko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nikgalushko"/>
    <language>en</language>
    <item>
      <title>Разбираем go:embed в Go 1.16</title>
      <dc:creator>Nikita Galushko</dc:creator>
      <pubDate>Tue, 26 Jan 2021 15:10:55 +0000</pubDate>
      <link>https://dev.to/nikgalushko/go-embed-go-1-16-4j8m</link>
      <guid>https://dev.to/nikgalushko/go-embed-go-1-16-4j8m</guid>
      <description>&lt;p&gt;Go 1.16 официально еще не вышел, но уже сейчас можно скачать бету с официального сайта и поиграться. Этим и займемся. В этой статье разберем работу нового пакет &lt;code&gt;embed&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  #0 устанавливаем beta go 1.16
&lt;/h2&gt;

&lt;p&gt;Если у вас установлен Go, то установка беты происходит максимально просто. В терминале выполняем последовательно следующие команды.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get golang.org/dl/go1.16beta1
go1.16beta1 download
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Вот и все, теперь бета доступна посредством вызова &lt;code&gt;go1.16beta1&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  embed
&lt;/h2&gt;

&lt;p&gt;Что если мы хотим встроить файл в наш бинарник на go, например, какие-то шаблоны, html файлы, если это веб сервер или даже README.md ? Нам приходилось либо саморучно затаскивать их в наш код, либо пользоваться сторонними библиотечками, такими как &lt;a href="https://github.com/go-bindata/go-bindata"&gt;go-bindata&lt;/a&gt;. Оба варианта отстойные. Первый способ не гибкий, в нем можно ошибиться, так как нужно все делать вручную. Второй способ получше, но это дополнительные зависимости, которых может не оказаться в вашей среде и главное дополнительные шаги при сборке приложения.&lt;/p&gt;

&lt;p&gt;Go 1.16 решает нашу проблему директивой &lt;code&gt;//go:embed path_pattern&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Условия использования директивы
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;директива должна предшествовать строке, содержащей объявление переменной, в которую будет помещен файл. Между директивой и объявлением переменной допускаются только пустые строки и комментарии&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;паттерн пути к файлу или директории не должен начинаться с &lt;code&gt;/&lt;/code&gt; и иметь в себе &lt;code&gt;.&lt;/code&gt; или &lt;code&gt;..&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;паттерн должен соответствовать хотя бы одному файлу или не пустой директории. В противном случае сборка не состоится&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;симлинки запрещено использовать в паттерне&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;паттерн может принимать только файлы или директории внутри модуля, но не во вне&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;чтобы получить все файлы в директории нужно использовать &lt;code&gt;*&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Встраиваем файл
&lt;/h2&gt;

&lt;p&gt;Директива &lt;code&gt;//go:embed&lt;/code&gt; позволяет нам встроить файла как строку &lt;code&gt;string&lt;/code&gt;, так и как слайс байт &lt;code&gt;[]byte&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;"log"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;//go:embed README.md&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;readme&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="c"&gt;//go:embed bkg.png&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&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;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readme&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;В данном примере файлы располагаются следующим образом:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── README.md
├── bkg.jpeg
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Теперь содержимое файла README.md лежит в перменное &lt;code&gt;readme&lt;/code&gt;, а содержимое bkg.png в переменной &lt;code&gt;image&lt;/code&gt;. При этом это обычные переменные, которые мы можем менять в ходе выполнения нашей программы. &lt;/p&gt;

&lt;h2&gt;
  
  
  Встраиваем несколько файлов aka embed.FS
&lt;/h2&gt;

&lt;p&gt;Мы поняли как встраивать один файл, но что делать, если у нас директория с несколькими html файлами, а еще директория с изображениями. Как нам встроить это все в наш бинарник ?&lt;/p&gt;

&lt;p&gt;На этот раз наш пакет будет выглядит так:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── README.md
├── bkg.jpeg
├── main.go
└── www
    ├── html
    │&amp;nbsp;&amp;nbsp; ├── about.html
    │&amp;nbsp;&amp;nbsp; └── index.html
    └── images
        ├── forest.jpg
        └── snow_forest.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;А код, которые встраивает в себя всю директорию www следующий:&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="s"&gt;"embed"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;//go:embed README.md&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;readme&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="c"&gt;//go:embed www&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;www&lt;/span&gt; &lt;span class="n"&gt;embed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FS&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;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"www/html"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&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;При этом &lt;code&gt;embed.FS&lt;/code&gt; реализует интерфейс &lt;a href="https://tip.golang.org/pkg/io/fs/#FS"&gt;fs.FS&lt;/a&gt;, что очень удобно для абстрагирования в коде откуда на самом деле он читает файлы.&lt;br&gt;
Для &lt;code&gt;embed.FS&lt;/code&gt; есть ряд ограничений:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;это строго read-only структура, так что можно свободно передавать ее в горутины&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;паттерн заканчивающийся на &lt;code&gt;/*&lt;/code&gt; встраивает все файлы даже те, которые начинаются на &lt;code&gt;.&lt;/code&gt; и на &lt;code&gt;_&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Пару слов напоследок
&lt;/h2&gt;

&lt;p&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="c"&gt;//go:embed bkg.jpeg&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;

&lt;span class="c"&gt;//go:embed bkg.jpeg&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;image2&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;то размер файла увеличится на 2 размера файла bkg.jpeg. При этом для встраивания через &lt;code&gt;embed.FS&lt;/code&gt; это не так.&lt;/p&gt;

&lt;p&gt;Больше статей на разные технические темы вы найдете у меня в &lt;a href="https://nikgalushko.com/"&gt;блоге&lt;/a&gt;.&lt;/p&gt;

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