<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Ilia Ushakov</title><generator>teletype.in</generator><description><![CDATA[Ilia Ushakov]]></description><image><url>https://img1.teletype.in/files/09/ab/09ab297e-3c29-47d2-90d1-153e3c804d0e.jpeg</url><title>Ilia Ushakov</title><link>https://teletype.in/@ushakov</link></image><link>https://teletype.in/@ushakov?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/ushakov?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/ushakov?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Sun, 05 Apr 2026 14:59:45 GMT</pubDate><lastBuildDate>Sun, 05 Apr 2026 14:59:45 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@ushakov/go-tags-in-tests</guid><link>https://teletype.in/@ushakov/go-tags-in-tests?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov</link><comments>https://teletype.in/@ushakov/go-tags-in-tests?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov#comments</comments><dc:creator>ushakov</dc:creator><title>Разделение тестов с помощью тегов сборки</title><pubDate>Wed, 27 Oct 2021 20:56:04 GMT</pubDate><description><![CDATA[В Go есть внутренний механизм для логического разделения тестов в зависимости от некоторых условий, в том числе условий на операционную систему или тип CPU. Так, например, можно отделить юнит тесты от интеграционных или от smoke тестов.]]></description><content:encoded><![CDATA[
  <p id="k3fo">В Go есть внутренний механизм для логического разделения тестов в зависимости от некоторых условий, в том числе условий на операционную систему или тип CPU. Так, например, можно отделить юнит тесты от интеграционных или от smoke тестов.</p>
  <h2 id="uewI">Что такое теги сборки?</h2>
  <p id="rPUJ">Тег сборки - это комментарий  в начале go-файла, который указывает компилятору, как стоит собирать этот конкретный файл.</p>
  <p id="hdK2">Например, при таком теге файл будет включен в сборку только в том случае, если компиляция выполняется под линукс (GOOS=linux)</p>
  <pre id="Ll47">// +build linux

package mypackage
...</pre>
  <p id="9o0n"></p>
  <p id="o6Eh">Тег сборки должен быть расположен в начале файла, а после строки с ним должна быть пустая строка.</p>
  <p id="Fod9">Также можно использовать оператор отрицания <code>!</code>. Таким образом, файл с тегом <code>// +build !linux</code> будет включен в сборку на всех платформах, кроме linux.</p>
  <p id="Hbrj">В тегах может быть несколько условий. Если условия расположены на одной строке, то они комбинируются через оператор OR. А если на нескольких строках, то через AND.</p>
  <pre id="wbhB">// +build linux darwin
// +build amd64

package mypackage
...</pre>
  <p id="gYcr">В примере выше файл будет включен в сборку только под <em>linux/amd64</em> или <em>darwin/amd64</em> платформы.</p>
  <p id="bmsz"></p>
  <h2 id="vM0n">Разделение тестов</h2>
  <p id="LEgC">Через теги сборки можно разделять разные виды тестов.</p>
  <p id="5b97">Рассмотрим 2 файла тестов:<br /><em>myfile_test.go:</em></p>
  <pre id="52Vy">package mypackage

import &quot;testing&quot;
...</pre>
  <p id="IMIR"></p>
  <p id="Xy3g"><em>myfile_integration_test.go:</em></p>
  <pre id="jG0r">// +build integration

package mypackage

import &quot;testing&quot;
...</pre>
  <p id="hQcI"></p>
  <p id="3f6Z">В файле <em>myfile_test.go</em> будут расположены unit тесты, а в <em>myfile_integration_test.go</em> - интеграционные (более медленные).</p>
  <p id="cI32">Поэтому при запуске тестов через <code>go test</code> запустятся тесты только из <em>myfile_test.go</em>. А если нужно запустить тесты из <em>myfile_integration_test.go</em>, то надо добавить флаг <code>—tags</code>. </p>
  <p id="dUGf"><code>go test --tags=integration</code></p>
  <p id="aTYo">Важно понимать, что при запуске <code>go test --tags=integration</code> так же запустятся unit тесты. Чтобы такого не произошло, надо добавить отрицание в теги сборки unit тестов.</p>
  <p id="QPnB"><em>myfile_test.go</em></p>
  <pre id="4MKr">// +build !integration

package mypackage

import &quot;testing&quot;
...</pre>
  <p id="zH2F"></p>
  <h2 id="1M1z">Итог</h2>
  <p id="jt2W">Есть несколько причин такого разделения тестов:</p>
  <ol id="287F">
    <li id="eVot">Интеграционные тесты значительно медленней unit тестов, поэтому их обычно стоит запускать только после успешного запуска unit тестов</li>
    <li id="rsyL">Компиляция под разные платформы</li>
    <li id="F29l">Smoke тесты, запускаемые на production приложение после деплоя.</li>
  </ol>
  <p id="WcU1"></p>
  <p id="E0H3"></p>
  <p id="BLzJ">Источник: <a href="https://mickey.dev/posts/go-build-tags-testing/" target="_blank">https://mickey.dev/posts/go-build-tags-testing/</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@ushakov/ceph</guid><link>https://teletype.in/@ushakov/ceph?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov</link><comments>https://teletype.in/@ushakov/ceph?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov#comments</comments><dc:creator>ushakov</dc:creator><title>Хранилище ceph</title><pubDate>Sun, 19 Sep 2021 11:19:23 GMT</pubDate><description><![CDATA[Очень хорошая статья про хранилище ceph на хабре]]></description><content:encoded><![CDATA[
  <p id="pvUo">Очень хорошая статья про хранилище ceph на <a href="https://habr.com/ru/post/313644" target="_blank">хабре</a></p>
  <p id="KX0A">Если коротко: </p>
  <blockquote id="YNpH">Ceph — это программно определяемая распределенная файловая система с открытым исходным кодом, лишенная узких мест и единых точек отказа, которая представляет из себя легко масштабируемый до петабайтных размеров кластер узлов, выполняющих различные функции, обеспечивая хранение и репликацию данных, а также распределение нагрузки, что гарантирует высокую доступность и надежность.</blockquote>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@ushakov/goproxy</guid><link>https://teletype.in/@ushakov/goproxy?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov</link><comments>https://teletype.in/@ushakov/goproxy?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov#comments</comments><dc:creator>ushakov</dc:creator><title>GOPROXY</title><pubDate>Sun, 19 Sep 2021 11:05:40 GMT</pubDate><description><![CDATA[Начиная с версии Go 1.13, стандартный менеджер пакетов в Go - это Go modules. Вместе с ним появилась переменная окружения GOPROXY, которая определяет, откуда будут скачиваться пакеты. ]]></description><content:encoded><![CDATA[
  <p id="8Cx7">Начиная с версии Go 1.13, стандартный менеджер пакетов в Go - это Go modules. Вместе с ним появилась переменная окружения GOPROXY, которая определяет, откуда будут скачиваться пакеты. </p>
  <p id="DDof">Посмотреть текущую конфигурацию:</p>
  <pre id="Clr2">~ ❯ go env GOPROXY
https://proxy.golang.org,direct</pre>
  <p id="91jE">В переменной GOPROXY будут указываться источники через запятую, откуда go будет пытаться скачать необходимый пакет. Если первый источник ответит 4xx, то go попробует скачать пакет по следующей ссылке. </p>
  <p id="5rO7">Direct указывает, что код надо загрузить по прямой ссылке из VCS. То есть ровно по той ссылке, как пакет импортируется в коде. </p>
  <p id="RXc0">Однако, загружать пакеты с VCS может быть не всегда безопасно. </p>
  <p id="u46l">Кто-то может внести вредоносный код в новых коммитах, или даже если вы строго зафиксировали версию пакета, с которым хотите работать, злоумышленник может изменить текущую версию кода через  <code>git push --force</code></p>
  <p id="i5pF">Сейчас по умолчанию в GOPROXY устанавливается <a href="https://proxy.golang.org" target="_blank">https://proxy.golang.org</a> как прокси и работает как кеш. То есть если в proxy.golang.org нужного пакета не найдется, то он его скачает и сразу же отдаст нам. Этот кеш гарантирует, что код не будет изменен. </p>
  <p id="swa8"></p>
  <p id="4414">Источники:</p>
  <p id="KGjr"><a href="https://golang.org/ref/mod#goproxy-protocol" target="_blank">https://golang.org/ref/mod#goproxy-protocol</a></p>
  <p id="n6ZU"><a href="https://jfrog.com/blog/why-goproxy-matters-and-which-to-pick/" target="_blank">https://jfrog.com/blog/why-goproxy-matters-and-which-to-pick/</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@ushakov/logging-levels</guid><link>https://teletype.in/@ushakov/logging-levels?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov</link><comments>https://teletype.in/@ushakov/logging-levels?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov#comments</comments><dc:creator>ushakov</dc:creator><title>Уровни логирования</title><pubDate>Sat, 18 Sep 2021 21:54:31 GMT</pubDate><description><![CDATA[У логов следует использовать разные уровни, так будет легче фильтровать и исследовать проблему по логам. ]]></description><content:encoded><![CDATA[
  <p id="WN4I">У логов следует использовать разные уровни, так будет легче фильтровать и исследовать проблему по логам. </p>
  <p id="JgUA">Так же можно будет настроить алерты только на определенный тип сообщений, и получать уведомления, когда в системе произошла серьезная ошибка. </p>
  <p id="zqEh">И можно будет настроить разный уровень сохранения/выводы логов. В таком случае при разработке можно включить вывод логов от <em>INFO </em>уровня, а на проде важно сохранять только сообщения уровня WARNING и выше.</p>
  <p id="dpl0">Ниже описаны основные уровни логов и причины их использовать:</p>
  <h2 id="vAMG">ERROR</h2>
  <p id="U5L7">В системе случилось что-то критичное, что влияет на бизнес процесс, на деньги, на пользователей. На такой тип ошибок должны быть настроены уведомления, чтобы даже ночью дежурные могли оперативно отреагировать на проблему. </p>
  <p id="e8rJ"><em>Например:  Внешний платежный шлюз перестал отвечать на наши запросы</em></p>
  <p id="9iPM"></p>
  <h2 id="1rob">WARNING</h2>
  <p id="0ppE">В системе произошла серьезная ошибка, но есть вероятность, что программа самостоятельно восстановится. При такой ошибке тоже надо уведомить дежурных, просто оперативная реакция не требуется. </p>
  <p id="TpNf"><em>Например:  На наш запрос не ответил внешний платежный шлюз. Дальше retry система попробует повторить запрос еще несколько раз. И если шлюз так и не ответит, то упадет ошибка <strong>ERROR</strong></em></p>
  <p id="pxmZ"></p>
  <h2 id="yayF">INFO</h2>
  <p id="QdhM">Произошло изменение в системе или в какой-то сущности. </p>
  <p id="I3sA"><em>Например: </em></p>
  <p id="SNFZ"><em>1. Система поднялась на порту 8080</em></p>
  <p id="C8l7"><em>2.  создан новый пользователь</em></p>
  <p id="bKg7"><em>3. вывод по cron задачу</em></p>
  <p id="kAxv"></p>
  <h2 id="OmEu">DEBUG</h2>
  <p id="dKlH">Служит для отладки приложения при разработке, или в случае, когда надо поймать что-то на проде. </p>
  <p id="rLT1"><em>Например: текущее значение какой-то переменной</em></p>
  <p id="mhc5"></p>
  <h2 id="yLNU">TRACE</h2>
  <p id="2jsw">Такой уровень логов нужен, чтобы отслеживать запросы внутри приложения.</p>
  <p id="clpO">Например: </p>
  <ol id="KquL">
    <li id="Xa5d">Пришел запрос на url /home</li>
    <li id="JKQi">Завершили обрабатывать запрос на /home за 0.5 секунд</li>
    <li id="0aDr">Начали/завершили обрабатывать метод</li>
  </ol>
  <p id="TJQk"></p>
  <p id="slhO">Источник: <a href="https://reflectoring.io/logging-levels" target="_blank">https://reflectoring.io/logging-levels</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@ushakov/unit-tests-with-scenarios</guid><link>https://teletype.in/@ushakov/unit-tests-with-scenarios?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov</link><comments>https://teletype.in/@ushakov/unit-tests-with-scenarios?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov#comments</comments><dc:creator>ushakov</dc:creator><title>Пишем unit тесты через сценарии</title><pubDate>Sat, 18 Sep 2021 20:11:47 GMT</pubDate><description><![CDATA[При таком подходе тест состоит из 3х частей:]]></description><content:encoded><![CDATA[
  <p id="U0Lq">При таком подходе тест состоит из 3х частей:</p>
  <ol id="21Jj">
    <li id="CpWh">Состояние системы на момент запуска теста</li>
    <li id="SV3s">Событие, которое изменяет состояние системы</li>
    <li id="2Spf">Результат - то, что должно произойти/измениться</li>
  </ol>
  <p id="5dZF">Для удобства предлагается разделить эти комментариями, чтобы не пытаться понять все через код. </p>
  <p id="16WM">Обратите внимание, что assert&#x27;ы выполняются только в третей части теста. </p>
  <figure>
    <script src="https://gist.github.com/ushakovme/274d12a54081388614a7e5d9a3e7ee87.js"></script>
  </figure>
  <p id="F2DY"></p>
  <p id="iLKk">Названия тестовых методов является продолжением фразы:  &quot;Что случается, когда ...&quot; </p>
  <figure>
    <script src="https://gist.github.com/ushakovme/8473c016c839a946325601f422346aee.js"></script>
  </figure>
  <p id="w9wY"></p>
  <p id="HyQe">Источник: <a href="https://matthiasnoback.nl/2021/09/write-unit-tests-like-scenario" target="_blank">https://matthiasnoback.nl/2021/09/write-unit-tests-like-scenario</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@ushakov/multistage-docker</guid><link>https://teletype.in/@ushakov/multistage-docker?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov</link><comments>https://teletype.in/@ushakov/multistage-docker?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov#comments</comments><dc:creator>ushakov</dc:creator><title>Собираем минимальный Docker образ для Golang приложений</title><pubDate>Sun, 12 Sep 2021 21:17:42 GMT</pubDate><description><![CDATA[<img src="https://img4.teletype.in/files/7e/24/7e24f47e-172c-4e3f-b3ee-2736fef502c9.png"></img>Обычный докер образ Golang приложения занимает порядка 600mb. ]]></description><content:encoded><![CDATA[
  <p id="6KL0">Обычный докер образ Golang приложения занимает порядка 600mb. </p>
  <p id="QddE">Чтобы облегчить образ, надо использовать multistage build. Это когда сначала все собирается в один образ, а потом результаты сборки копируются в другой. А инструменты сборки и все лишнее не копируются. </p>
  <p id="Cka6"></p>
  <figure>
    <script src="https://gist.github.com/ushakovme/a53c17d5f4f5c4c5eda56722f574ce05.js"></script>
  </figure>
  <p id="eaL8"></p>
  <p id="B3yw">Так итоговый образ получился размером 4.3MB</p>
  <figure id="3HVC" class="m_original">
    <img src="https://img4.teletype.in/files/7e/24/7e24f47e-172c-4e3f-b3ee-2736fef502c9.png" width="800" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@ushakov/first-post</guid><link>https://teletype.in/@ushakov/first-post?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov</link><comments>https://teletype.in/@ushakov/first-post?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=ushakov#comments</comments><dc:creator>ushakov</dc:creator><title>hi</title><pubDate>Sun, 05 Sep 2021 18:54:28 GMT</pubDate><description><![CDATA[jjjjj]]></description><content:encoded><![CDATA[
  <pre id="ynZe">$ git add articles/wizard-of-oz.txt
$ git commit -m &#x27;wrote the wizard of oz.</pre>
  <hr />
  <p id="pj8I">jjjjj</p>

]]></content:encoded></item></channel></rss>