{"version":"https://jsonfeed.org/version/1.1","title":"Vic Demuzere - Go","home_page_url":"https://vic.demuzere.be/articles/tags/go/","feed_url":"https://vic.demuzere.be/articles/tags/go/feed.json","description":"Blog posts tagged Go by Vic Demuzere","language":"en","items":[{"id":"https://vic.demuzere.be/articles/environment-variables-setenv-ssh-golang/","content_html":"<p>One of the tools I'm maintaining at work is Bunka, a Go CLI application to execute commands in parallel on a list of servers.\nWe're setting the <code>DEBIAN_FRONTEND</code> environment variable to <code>noninteractive</code> for all our connections as we regularly use <code>apt</code> and related commands.\n(If we don't, command execution may hang as a dialog is shown and the process is waiting for user input.)</p>\n<p>This week someone created a bug report because their <code>apt-get</code> commands were hanging on multiple servers.\nPretty strange, as this was the exact reason we're setting environment variables in the first place. Let's investigate!</p>\n<h2 id=\"changing-the-environment-in-go\">Changing the environment in Go<a href=\"#changing-the-environment-in-go\" aria-label=\"Link to heading 'Changing the environment in Go'\" data-heading-content=\"Changing the environment in Go\" class=\"anchor\"></a></h2>\n<p>To change environment variable for the currently running process you can use the <code>Setenv</code> function provided by the standard library's <code>os</code> package.\nThis can be useful when you use the <code>os/exec</code> package to start subprocesses.</p>\n<pre><code class=\"language-go\">func Setenv(key, value string) error \n</code></pre>\n<p>The <a href=\"https://pkg.go.dev/golang.org/x/crypto/ssh\" title=\"Golang x/crypto/ssh package\">ssh</a> package provides a similar function that sets an environment variable on an SSH session.\nThese variables will be available for any command you execute on that same session after changing calling the <code>Setenv</code> function.</p>\n<pre><code class=\"language-go\">func (s *Session) Setenv(name, value string) error\n</code></pre>\n<p>As this &quot;simply sets a variable&quot; I was ignoring the errors returned by the <code>Setenv</code> function. After all, what could go wrong when setting a simple environment variable? I couldn't be more wrong.</p>\n<h2 id=\"ssh-setenv-failed\">ssh: setenv failed<a href=\"#ssh-setenv-failed\" aria-label=\"Link to heading 'ssh: setenv failed'\" data-heading-content=\"ssh: setenv failed\" class=\"anchor\"></a></h2>\n<p>When I actually checked the error object returned by <code>Setenv</code> it turned out not to be nil. It contained the amazingly useful message below.</p>\n<pre><code>ssh: setenv failed\n</code></pre>\n<p>Diving in the source code for the <code>ssh</code> package we can see that the request to set an environment variable is sent directly to the SSH server, there's not much in that Go code that can go wrong. Also note that it returns the same error message regardless of what went wrong when calling <code>SendRequest</code>.</p>\n<pre><code class=\"language-go\">func (s *Session) Setenv(name, value string) error {\n\tmsg := setenvRequest{\n\t\tName:  name,\n\t\tValue: value,\n\t}\n\tok, err := s.ch.SendRequest(&quot;env&quot;, true, Marshal(&amp;msg))\n\tif err == nil &amp;&amp; !ok {\n\t\terr = errors.New(&quot;ssh: setenv failed&quot;)\n\t}\n\treturn err\n}\n</code></pre>\n<p>So let's take a step back and do it without Go:</p>\n<pre><code>[vic@local ~]$ export DEBIAN_FRONTEND=noninteractive\n[vic@local ~]$ ssh -o SendEnv=DEBIAN_FRONTEND vic@remote\n[vic@remote ~]# echo $DEBIAN_FRONTEND\n</code></pre>\n<p>Nothing, it simply doesn't work.</p>\n<h2 id=\"allowing-environment-variables-over-ssh\">Allowing environment variables over SSH<a href=\"#allowing-environment-variables-over-ssh\" aria-label=\"Link to heading 'Allowing environment variables over SSH'\" data-heading-content=\"Allowing environment variables over SSH\" class=\"anchor\"></a></h2>\n<p>Turns out, you can't simply change environment variables in SSH sessions. The OpenSSH server denies those requests unless you've whitelisted the specific variable in your server settings. This is for security reasons: people with access to a restricted list of commands could set an environment variable like <code>LD_PRELOAD</code> to escape their jail. (If your user has access to a shell there are other ways to set environment variables.)</p>\n<p>To allow changing an environment variable over SSH, change the <code>AcceptEnv</code> setting in your <a href=\"https://manpages.debian.org/unstable/openssh-server/sshd_config.5.en.html#AcceptEnv_2\" title=\"OpenSSH sshd_config man page: AcceptEnv\">OpenSSH server configuration</a> (typically <code>/etc/ssh/sshd_config</code>) to accept your environment variable:</p>\n<pre><code>AcceptEnv DEBIAN_FRONTEND\n</code></pre>\n<p>And now it magically works!</p>\n<div class=\"footer\"><hr><p>Thanks for subscribing to my feed!</p><p>Feel free to e-mail comments or corrections to <a href=\"mailto:vic@demuzere.be?subject=RE%3A%20SSH%20environment%20variables%20in%20Go\">vic@demuzere.be</a>.</p></div>","url":"https://vic.demuzere.be/articles/environment-variables-setenv-ssh-golang/","date_published":"2020-02-11T19:15:00Z","date_modified":"2025-02-08T09:27:38Z","language":"en"},{"id":"https://vic.demuzere.be/articles/naar-londen-voor-golang-uk-2016/","content_html":"<p>Sinds kort schrijven we bij <a href=\"https://www.combell.com/nl/openminds-is-nu-combell\">Openminds</a> enkele interne tools in Go. De tweede editie van GolangUK was dan ook een goede gelegenheid om deze taal beter te leren kennen. De conferentie vond plaats in de prachtige gebouwen van The Brewery in Londen.</p>\n<p><img src=\"https://vic.demuzere.be/assets/articles/images/ysz51v8FGjZ3NRJ4U5NQEl4o39AuqWRd.jpg\" alt=\"Welcome to Golang UK conference\" /></p>\n<p>Maar eerst: waarom is de populariteit van Go zo sterk toegenomen? Go wordt naar statisch gelinkte binaries gecompileerd. Met andere woorden: ze kunnen overal uitgevoerd worden zonder externe afhankelijkheden. Daarnaast zijn simpele tooltjes ook iets sneller dan de Ruby-varianten die we vroeger gebruikten.</p>\n<h2 id=\"dag-1---workshop\">Dag 1 - Workshop<a href=\"#dag-1---workshop\" aria-label=\"Link to heading 'Dag 1 - Workshop'\" data-heading-content=\"Dag 1 - Workshop\" class=\"anchor\"></a></h2>\n<p>Voorafgaand aan GolangUK waren twee workshops voorzien. De keuze bestond uit de <strong>Ultimate Go Workshop</strong> die een introductie tot de programmeertaal gaf voor mensen die voorlopig enkel ervaring hadden met andere talen. In de <strong>Advanced Go Workshop</strong>, voor iedereen die wel al iets in Go geknutseld heeft, keken we naar het belang van data-oriented design: goed doordachte datastructuren kunnen een groot verschil maken in performantie. Er werd gehamerd op het belang van simpele en makkelijk te lezen code. Later kwamen ook de verschillende tools aan bod die helpen met het opsporen van code die veel CPU-tijd kost of veel geheugen verbruikt.</p>\n<h3 id=\"joren-koos-voor-de-ultimate-go-workshop\"><a href=\"https://twitter.com/joren\">Joren</a> koos voor de Ultimate Go Workshop<a href=\"#joren-koos-voor-de-ultimate-go-workshop\" aria-label=\"Link to heading 'Joren koos voor de Ultimate Go Workshop'\" data-heading-content=\"Joren koos voor de Ultimate Go Workshop\" class=\"anchor\"></a></h3>\n<p>Met nog niet veel Go-ervaring was het fijn om ondergedompeld te worden in de <strong>structuren en details</strong> van Go. Dit heeft geholpen om de rest van de conferentie toch wat beter te begrijpen. Komende van een Ruby-achtergrond zijn er toch wel een hoop ideeën die helemaal anders zijn in Go. Een dagje experimenteren met Go was dan ook zeer leerrijk.</p>\n<p><img src=\"https://vic.demuzere.be/assets/articles/images/zYDj9vh4vkbAe2LMNAxjCIJfzr4PV7Kg.jpg\" alt=\"Joren op de Ultimate Go workshop\" /></p>\n<p>Voor wie zelf eens door alle <strong>voorbeelden en oefeningen</strong> wil gaan, is er goed nieuws. Alles staat online en met behulp van <a href=\"https://play.golang.org\">play.golang.org</a> kan je ook meteen beginnen spelen met code.</p>\n<h3 id=\"ik-trok-naar-de-advanced-go-workshop\">Ik trok naar de Advanced Go Workshop<a href=\"#ik-trok-naar-de-advanced-go-workshop\" aria-label=\"Link to heading 'Ik trok naar de Advanced Go Workshop'\" data-heading-content=\"Ik trok naar de Advanced Go Workshop\" class=\"anchor\"></a></h3>\n<p>Deze was helemaal <strong>niet zo praktisch als ik had verwacht</strong>. Het bleek een presentatie met input van het publiek te zijn, dus wat dat betreft was ik een <strong>beetje teleurgesteld</strong>. Het enthousiasme van de presentator maakte dat wel goed. <a href=\"https://twitter.com/goinggodotnet\">William Kennedy</a> is waarschijnlijk de <strong>meest enthousiaste verteller</strong> die ik ooit heb gezien. Zijn verhaal was vrij abstract, maar de ludieke voorbeelden en grapjes tussendoor zorgen er wel voor dat zijn boodschap bleef hangen. Zelf onthoud ik vooral <strong>het belang van goed gestructureerde code</strong>. Iets wat in onze interne go-projectjes momenteel wat achterblijft. Werk aan de winkel dus!</p>\n<p>Na de workshops was er afgesproken om iets te gaan drinken in een lokale pub, daar kwam echter niet veel volk opdagen. De workshops waren ook iets optioneels vooraf aan de conferentie waardoor er sowieso minder mensen waren.</p>\n<h2 id=\"dag-2---conference-day-1\">Dag 2 - Conference Day 1<a href=\"#dag-2---conference-day-1\" aria-label=\"Link to heading 'Dag 2 - Conference Day 1'\" data-heading-content=\"Dag 2 - Conference Day 1\" class=\"anchor\"></a></h2>\n<p>Donderdagochtend lag de focus (zoals in de workshop) opnieuw op het schrijven van <strong>idiomatische code</strong>. Een verzamelnaam voor verschillende afspraken en richtlijnen die de Go-community heeft om code duidelijk, leesbaarder en efficient te maken.</p>\n<p><img src=\"https://vic.demuzere.be/assets/articles/images/VKl6elroLDVaMissWUc8SHcofGvHOEUr.jpg\" alt=\"Golang UK conferentie - grote zaal\" /></p>\n<p>De trend van <strong>microservices</strong> en <strong>containers</strong> is ook duidelijk zichtbaar, misschien zelfs een beetje te veel. De onderwerpen tracability (het opsporen van requests doorheen verschillende services), logging en statistieken via <a href=\"https://prometheus.io/\">Prometheus</a> komen vaak terug. Ook talks die over iets anders lijken te gaan raken vaak aan het onderwerp. De focus had wat meer over de Go-taal zelf mogen liggen.</p>\n<p>Donderdagavond was eindelijk het moment aangebroken waarvoor iedereen stiekem kwam: het sociale event. Buiten was een <em>we-doen-alsof-we-in-een-tropisch-land-zitten</em> terrasje ingericht en de organisatie zorgde voor een lekkere barbecue.</p>\n<p>De <strong>catering</strong> op GolangUK was overigens tijdens heel de conferentie <strong>dik in orde</strong>! We konden zelf onze gerechten samenstellen door 3 soorten koude slaatjes (vlees, vis of enkel groenten) te combineren met 3 keuzes in warme gerechtjes: ook weer vlees, vis of vegetarisch.</p>\n<h2 id=\"dag-3---conference-day-2\">Dag 3 - Conference Day 2<a href=\"#dag-3---conference-day-2\" aria-label=\"Link to heading 'Dag 3 - Conference Day 2'\" data-heading-content=\"Dag 3 - Conference Day 2\" class=\"anchor\"></a></h2>\n<p>De eerste interessante talk was &quot;<strong>How to raise a Gopher</strong>&quot;, waarin <a href=\"https://twitter.com/tiffanyfayj\">Tiffany Jernigan</a> uitlegt hoe ze in korte tijd Go heeft geleerd en haar ervaring met ons deelt. Heel interessant, vooral omdat bij Openminds ook veel mensen voor de eerste keer in contact komen met de programmeertaal. Ze gaf een <strong>mooi overzicht</strong> van de online (en in mindere mate geprinte) bronnen die haar geleerd hebben hoe ze in Go aan de slag moest.</p>\n<p>Daarna, bij gebrek aan beter, een inkijk in iOS en Android apps die gebruikmaken van <strong>Go Mobile</strong>. Het idee is dat de mobiele apps nog steeds in de native talen voor elk van beide platformen geschreven worden, maar dat ze wel gebruik kunnen maken van een <strong>Go-library</strong> voor de gedeelde logica. De Go Mobile tool zorgt voor de nodige koppelingen.</p>\n<p>De beste talk van vrijdag was van <strong>Liz Rice</strong>, die op een verrassend interessante manier toonde wat een container nu eigenlijk is. Waar de meesten een ingewikkelde rede over namespaces en cgroups voeren, implementeerde Liz een <strong>container in Go</strong>. Stap per stap, of eerder syscall per syscall, toonde ze hoe een proces meer en meer afgezonderd werd van de rest van het systeem. In een klein half uurtje had ze zo een Go-programma met een eigen filesystem, hostname en afgezonderde procesnummers (PIDs).</p>\n<p>Ook op vrijdag bleken veel talks te raken aan de <strong>microservices</strong>, dus het was soms een beetje zoeken om niet nog eens dezelfde argumenten te horen.</p>\n<h2 id=\"the-end\">The end<a href=\"#the-end\" aria-label=\"Link to heading 'The end'\" data-heading-content=\"The end\" class=\"anchor\"></a></h2>\n<p>GolangUK had helaas <strong>geen closing keynote</strong> om op een mooie manier af te sluiten. Na de laatste presentatie was de conferentie plots gedaan. Daar schoot de verder prima verlopen conferentie toch iets te kort.</p>\n<p>Voor we dag nadien naar huis vertrekken toch nog eens opscheppen (pun intended) aan het ontbijt.</p>\n<div class=\"footer\"><hr><p>Thanks for subscribing to my feed!</p><p>Feel free to e-mail comments or corrections to <a href=\"mailto:vic@demuzere.be?subject=RE%3A%20Naar%20londen%20voor%20GolangUK%202016\">vic@demuzere.be</a>.</p></div>","url":"https://vic.demuzere.be/articles/naar-londen-voor-golang-uk-2016/","date_published":"2016-08-30T12:00:00Z","date_modified":"2026-05-13T17:21:53Z","language":"nl"},{"id":"https://vic.demuzere.be/articles/golang-makefile-crosscompile/","content_html":"<p>When a new version of one of my Go apps is ready, I usually want to build and package the binary for multiple platforms.\nThis can easily be done in a shell script, but Make brings a bonus: it can run multiple builds at the same time.</p>\n<h2 id=\"makefile-101\">Makefile 101<a href=\"#makefile-101\" aria-label=\"Link to heading 'Makefile 101'\" data-heading-content=\"Makefile 101\" class=\"anchor\"></a></h2>\n<p>In case you've worked with make before, skip this section!\nIf not: let's see what a basic makefile looks like.</p>\n<p>Make defines <strong>targets</strong>, these are things that need to be done.\nUsually a target represents a file that has to be created.\nEvery target contains a list of commands that have to be executed, we call that the <strong>recipe</strong>.\nMake will only execute the recipe if a file with the same name as the target does not exist.\nIf your target does not represent a file, it's a <em>phony target</em>.</p>\n<pre><code>mytarget:\n\techo Hello world.\n\nspace: mytarget foo\n\techo &quot;I'm in space.&quot;\n\nfoo:\n\techo I am run only once\n\ttouch foo\n\n.PHONY: mytarget space\n</code></pre>\n<p>The above makefile contains 3 targets: <code>mytarget</code>, <code>foo</code> and <code>space</code>.\nThe second target tells us that it needs both other targets, so when you call <code>make space</code>, make will also execute <code>mytarget</code> and <code>foo</code>.</p>\n<p>At the bottom of the file we define a special .PHONY target: Here we simply tell make which targets are phony targets.\nThose do not represent a file on disk.\nAs we usually don't compile separate Go files, most of our targets will be phony targets.</p>\n<p>Let's see what this does: save the file as <code>Makefile</code> and run <code>make space</code> in the same directory:</p>\n<pre><code>$ make space  \necho Hello world.\nHello world.\necho I am run only once\nI am run only once\necho &quot;I'm in space.&quot;\nI'm in space.\n</code></pre>\n<p>Notice that make always tells us what command it is executing.\nYou can hide a command by prefixing it with @.\nAs we'll be executing multiple targets concurrently, it may be useful to see which commands are running.</p>\n<p>Run <code>make space</code> again.\nYou'll see that the <code>foo</code> target is not run anymore.\nThat's because we created a file named foo and <code>foo</code> is not a phony target.</p>\n<h3 id=\"variables\">Variables<a href=\"#variables\" aria-label=\"Link to heading 'Variables'\" data-heading-content=\"Variables\" class=\"anchor\"></a></h3>\n<p>GNU Make has two types of variables.\nWhen we assign to a variable with <code>:=</code> the contents is evaluated at the time the variable is declared.\nIf we use just <code>=</code> the contents is evaluated every time we use the variable.</p>\n<pre><code>MYVAR := Hello there! I am currently in $(shell pwd)\nPWD = $(shell pwd)\n</code></pre>\n<p>The <code>pwd</code> shell command will be executed every time we use variable <code>$(PWD)</code> in the makefile, while <code>$(MYVAR)</code> will always contain the same value.</p>\n<h2 id=\"cross-compiling\">Cross compiling<a href=\"#cross-compiling\" aria-label=\"Link to heading 'Cross compiling'\" data-heading-content=\"Cross compiling\" class=\"anchor\"></a></h2>\n<p>Make supports running multiple targets at the same time.\nThis means that we need a separate target for every GOOS and GOARCH in order to take advantage of the concurrency.</p>\n<p>A simple way to do this would be:</p>\n<pre><code>linux:\n\tGOOS=linux GOARCH=amd64 go build ...\n\nwindows:\n\tGOOS=windows GOARCH=amd64 go build ...\n\nrelease: windows linux\n\n.PHONY release windows linux\n</code></pre>\n<p>This builds both linux and windows binaries when we call <code>make release</code>.\nWe can improve this Makefile by looping over the platforms and architectures we want to build:</p>\n<pre><code>PLATFORMS := linux/amd64 windows/amd64\n\nrelease: $(PLATFORMS)\n\n$(PLATFORMS):\n\techo Hello, I am $@\n\n.PHONY release $(PLATFORMS)\n</code></pre>\n<p>What we do here is create a target that contains all possible platforms.\nEvery platform is a separate target, just like it was in the previous Makefile.\nThat also means that we have to add every platform to the phony list.\nLuckily, we can do that using the same variable. Inside the recipe we can use the special <code>$@</code> that contains the name of the current target.</p>\n<p>The next part is a bit harder, we need to separate OS and ARCH.\nRemember that variables can be evaluated at runtime?\nWe'll use that feature to create an <code>$(os)</code> and <code>$(arch)</code> var.</p>\n<pre><code>temp = $(subst /, ,$@)\nos = $(word 1, $(temp))\narch = $(word 2, $(temp))\n</code></pre>\n<p>String manipulation functions in make are limited, so we have to be a bit creative here.\nWe'll use these variables inside the <code>$(PLATFORM)</code> target.\nRemember that <code>$@</code> contains the name of the current target?\nWhen we replace the slash in this string we can use the <code>word</code> function to get the first and last part.</p>\n<p>Combined with our previous Makefile, this becomes:</p>\n<pre><code>PLATFORMS := linux/amd64 windows/amd64\n\ntemp = $(subst /, ,$@)\nos = $(word 1, $(temp))\narch = $(word 2, $(temp))\n\nrelease: $(PLATFORMS)\n\n$(PLATFORMS):\n\tGOOS=$(os) GOARCH=$(arch) go build -o '$(os)-$(arch)' mypackage\n\n.PHONY release $(PLATFORMS)\n</code></pre>\n<p>Note that variables can only be set outside the recipe.\nAs the contents is only evaluated when we use them, it still contains the correct value.</p>\n<h2 id=\"concurrency\">Concurrency<a href=\"#concurrency\" aria-label=\"Link to heading 'Concurrency'\" data-heading-content=\"Concurrency\" class=\"anchor\"></a></h2>\n<p>We now have a Makefile that creates binaries for the platforms we listed in the <code>$(PLATFORMS)</code> variable.\nWhen we call <code>make release</code> it builds everything we asked, one by one.\nThe main reason to use make is the easy concurrency: simply call make with the <code>-j n</code> argument, where n is the number of simultaneous jobs.</p>\n<div class=\"footer\"><hr><p>Thanks for subscribing to my feed!</p><p>Feel free to e-mail comments or corrections to <a href=\"mailto:vic@demuzere.be?subject=RE%3A%20Cross%20compiling%20Go%20applications%20with%20Make\">vic@demuzere.be</a>.</p></div>","url":"https://vic.demuzere.be/articles/golang-makefile-crosscompile/","date_published":"2016-06-06T21:47:00Z","date_modified":"2024-11-11T18:06:57Z","language":"en"}]}