<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tobiasz&#39;s blog</title><link>/</link><description>Recent content on Tobiasz&#39;s blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Sat, 02 Nov 2019 00:00:00 +0000</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml"/><item><title>About me</title><link>/about/</link><pubDate>Wed, 09 Apr 2014 00:00:00 +0000</pubDate><guid>/about/</guid><description>&lt;p&gt;My name is &lt;strong&gt;Tobiasz Heller&lt;/strong&gt; and I am working as a backend developer at &lt;a href=&#34;https://www.ingrid.com/&#34;&gt;Ingrid&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In everyday work I use Go, Kubernetes, Prometheus, and other cloud-native technologies.&lt;/p&gt;
&lt;p&gt;I am also a regular speaker at &lt;a href=&#34;https://www.meetup.com/pl-PL/gowroc/&#34;&gt;GoWroc&lt;/a&gt; meetup and all my talks can be found at &lt;a href=&#34;https://github.com/tobiaszheller/talks&#34;&gt;github&lt;/a&gt; or at &lt;a href=&#34;https://www.youtube.com/channel/UCLYHbPSELXECxBpQNPZnuxg&#34;&gt;youtube channel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can reach me at twitter &lt;a href=&#34;https://twitter.com/tobiaszheller/&#34;&gt;@tobiaszheller&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Configure Go app using envconfig and struct embedding</title><link>/posts/envconfig/</link><pubDate>Sat, 02 Nov 2019 00:00:00 +0000</pubDate><guid>/posts/envconfig/</guid><description>
&lt;p&gt;Environment variables are great. If you are not using them to pass configuration into your app, you should take a look at &lt;a href=&#34;https://12factor.net/config&#34;&gt;12 Factor App - config&lt;/a&gt;, it&amp;rsquo;s explained easily and clearly.&lt;/p&gt;
&lt;p&gt;Reading environment variables in Go is very simple:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-Go&#34; data-lang=&#34;Go&#34;&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;import&lt;/span&gt; (
&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;
)
&lt;span style=&#34;font-weight:bold&#34;&gt;func&lt;/span&gt; main() {
fmt.Printf(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;Debug env is set to: &amp;#39;%s&amp;#39;\n&amp;#34;&lt;/span&gt;, os.Getenv(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;USE_DEBUG&amp;#34;&lt;/span&gt;))
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;we-can-do-better&#34;&gt;We can do better!&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;os.Getenv&lt;/code&gt; is a great building block, however often you need to read 10+ variables in your application.
Building config struct out of it using &lt;code&gt;os&lt;/code&gt; package results in a lot of boilerplate code.
Additional complexity is added when you want to parse other types than string.&lt;/p&gt;
&lt;p&gt;For all microservices that I am building in Go I am using &lt;a href=&#34;https://github.com/kelseyhightower/envconfig&#34;&gt;kelseyhightower/envconfig&lt;/a&gt;.
It is very straightforward, let&amp;rsquo;s take a look at some code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-Go&#34; data-lang=&#34;Go&#34;&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt; config &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
Timeout time.Duration &lt;span style=&#34;font-style:italic&#34;&gt;`default:&amp;#34;5m&amp;#34; `&lt;/span&gt;
Debug &lt;span style=&#34;&#34;&gt;bool&lt;/span&gt;
SupportedCountries []&lt;span style=&#34;&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;`envconfig:&amp;#34;SUPPORTED_COUNTRIES&amp;#34;`&lt;/span&gt;
}
&lt;span style=&#34;font-weight:bold&#34;&gt;func&lt;/span&gt; main() {
&lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; cfg config
&lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; err := envconfig.Process(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &amp;amp;cfg); err != &lt;span style=&#34;font-weight:bold&#34;&gt;nil&lt;/span&gt; {
log.Fatal(err)
}
log.Printf(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;%+v\n&amp;#34;&lt;/span&gt;, cfg)
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Envconfig decodes environment variables into provided struct.
By default envoconfig will update only the fields which has corresponded environment variables.&lt;/p&gt;
&lt;p&gt;You can specify a more accurate name on env side using struct tags &lt;code&gt;envconfig:&amp;quot;MY_ENV&amp;quot;&lt;/code&gt;.
Using struct tags you can also define required and default values.&lt;/p&gt;
&lt;h2 id=&#34;my-favorite-part-struct-embedding&#34;&gt;My favorite part - struct embedding&lt;/h2&gt;
&lt;p&gt;If you build a lot of microservices, it will result in a lot of internal libraries that you share among services.
Often you need to pass config to them and you would like to change it via environment variables.&lt;/p&gt;
&lt;p&gt;Using envconfig and struct embedding it is really easy.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create our internal package &lt;code&gt;sftp&lt;/code&gt; and define the following struct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-Go&#34; data-lang=&#34;Go&#34;&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;package&lt;/span&gt; sftp
&lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt; Config &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
Username &lt;span style=&#34;&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;`envconfig:&amp;#34;SFTP_USERNAME&amp;#34;`&lt;/span&gt;
Password Password &lt;span style=&#34;font-style:italic&#34;&gt;`envconfig:&amp;#34;SFTP_PASSWORD&amp;#34;`&lt;/span&gt;
Hostname &lt;span style=&#34;&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;`envconfig:&amp;#34;SFTP_HOSTNAME&amp;#34;`&lt;/span&gt;
Directory &lt;span style=&#34;&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;`envconfig:&amp;#34;SFTP_DIRECTORY&amp;#34;`&lt;/span&gt;
}
&lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt; Password &lt;span style=&#34;&#34;&gt;string&lt;/span&gt;
&lt;span style=&#34;font-weight:bold&#34;&gt;func&lt;/span&gt; (Password) String() &lt;span style=&#34;&#34;&gt;string&lt;/span&gt; {
&lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;***&amp;#34;&lt;/span&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you can import it in you microservice by embedding &lt;code&gt;sftp.Config&lt;/code&gt; into config struct that you already have there. You can also define it as new type if you want to import more then 1 config struct.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-Go&#34; data-lang=&#34;Go&#34;&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt; config &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
Timeout time.Duration &lt;span style=&#34;font-style:italic&#34;&gt;`default:&amp;#34;5m&amp;#34; `&lt;/span&gt;
Debug &lt;span style=&#34;&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;`required:&amp;#34;true&amp;#34;`&lt;/span&gt;
SupportedCountries []&lt;span style=&#34;&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;`envconfig:&amp;#34;SUPPORTED_COUNTRIES&amp;#34;`&lt;/span&gt;
SftpConfig
}
&lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt; SftpConfig sftp.Config&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you provide sftp config via environment variables and parse main &lt;code&gt;cfg&lt;/code&gt; you will see that config is populated correctly and you can pass &lt;code&gt;cfg.SftpConfig&lt;/code&gt; into your &lt;code&gt;sftp&lt;/code&gt; package.
Using that approach you can tweak the config of your internal library just by using env variables.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/kelseyhightower/envconfig&#34;&gt;kelseyhightower/envconfig&lt;/a&gt; is a very simple and powerful library that helps you to parse environment variables into struct.
It supports parsing into multiple data types and you can define defaults and required parameters.&lt;/p&gt;
&lt;p&gt;If you are using some internal libraries you can pass config to them using envconfig by adding library config struct into your main configuration using struct embedding.
You can find an example code at my &lt;a href=&#34;https://github.com/tobiaszheller/blog-examples/tree/master/envconfig&#34;&gt;github&lt;/a&gt;.&lt;/p&gt;</description></item></channel></rss>