<?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: Michele Caci</title>
    <description>The latest articles on DEV Community by Michele Caci (@mcaci).</description>
    <link>https://dev.to/mcaci</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%2F250257%2Fc6b0ba93-72c2-4cbb-a0b3-4b3f8fe90e89.jpeg</url>
      <title>DEV Community: Michele Caci</title>
      <link>https://dev.to/mcaci</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mcaci"/>
    <language>en</language>
    <item>
      <title>A Go-cus after GopherConEU 2023</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Mon, 17 Jul 2023 07:15:47 +0000</pubDate>
      <link>https://dev.to/mcaci/a-go-cus-after-gopherconeu-2023-55ih</link>
      <guid>https://dev.to/mcaci/a-go-cus-after-gopherconeu-2023-55ih</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3oiMp7Jw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j3bf1mjapdr5xdlaz78h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3oiMp7Jw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j3bf1mjapdr5xdlaz78h.png" alt="GopherConEU23" width="800" height="373"&gt;&lt;/a&gt;&lt;br&gt;
Because if there has been a &lt;a href="https://twitter.com/gopherconeu/status/1674036578962776068/photo/1"&gt;bin-go&lt;/a&gt;, there can be a go-cus (or a focus on Go).&lt;/p&gt;

&lt;p&gt;Some time has passed since GopherConEU 2023, held in June 27th to 29th, and I wish to take this occasion to share with you my experience of these amazing days and my thoughts about the areas where Go has shown to focus more using the content of what was shared in the various talks and the chatter with the various Gophers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: GopherConEU is one of the best places to have an idea of what is going on about Go, especially going in person, as this makes you learn not only from the content of the conference but also from meeting and talking to the Gophers around you.&lt;/p&gt;

&lt;h2&gt;
  
  
  An overview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sj_rCYUX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfj9qmqoc41ywgls99zw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sj_rCYUX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfj9qmqoc41ywgls99zw.jpeg" alt="Welcome back" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Welcome back&lt;/b&gt;



&lt;p&gt;For those who don't know yet what GopherConEU is, it is the European conference for all topics related to Go.&lt;/p&gt;

&lt;p&gt;Every edition of GopherConEU, this being the 6th, has been organized in a different location, but since last year it was localized in Berlin at the Festsaal Kreuzberg.&lt;/p&gt;

&lt;p&gt;For GopherConEU 2023 I was able to participate to the workshop and the two days of talks. I was not able to arrive in time to join the social events at the beginning of the talk but it did not prevent me to meet very nice people during the conference days. I sure felt the friendly atmosphere that sourrounds the Go community during the conference and everyone was eager to meet and to exchange not only about Go but also their passions and interests.&lt;/p&gt;

&lt;p&gt;To share my experience and my idea of what stood out during the GopherConEU this year, I'm going to focus on some specific topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;A focus on the Go community&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Go-ing to next level&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;The importance of security&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A focus on the Go community
&lt;/h2&gt;

&lt;p&gt;Go is primarily made by the Go team. During GopherConEU this sear there were several talks from the Go team members and other Google software engineers who made some highlights about few new features and tools, like the talks of &lt;strong&gt;Jonathan Amsterdam&lt;/strong&gt; about the new &lt;strong&gt;slog&lt;/strong&gt; package coming in go v1.21, the one about &lt;strong&gt;service weaver&lt;/strong&gt;, made by &lt;em&gt;Robert Grandl&lt;/em&gt;, a framework recently released by Google to be able to modularize a Go binary into services that can be easily deployed as microservices and the lightning talk from Robert Burke who made me excited to go get go version v1.21 and experiment the &lt;a href="https://tip.golang.org/doc/go1.21#language"&gt;updates&lt;/a&gt; on generics.&lt;/p&gt;

&lt;p&gt;But what stood out the most during these three days was the fact that the community itself is growing more and more, adopting Go to experiment and create all sorts of applications and pacakges and, most of all, sharing its experiences with the rest of the community.&lt;/p&gt;

&lt;p&gt;This was highlighted not only by the keynote given by Cameron Balahan, the product lead of Go, about the state of Go, but also on the concrete examples of some on the talks given during the conference.&lt;/p&gt;

&lt;p&gt;Take for example the talk about the tips to &lt;strong&gt;reduce memory consumption&lt;/strong&gt; on Go by &lt;strong&gt;Yiscah Levy Silas&lt;/strong&gt; where she shared her experience about memory allocations and exploit this knowledge to make the right choices and reduce the memory footprint of your applications. In another example you can take the talk from &lt;strong&gt;Drishti Jain&lt;/strong&gt; where she explained which libraries and concepts we need to know to &lt;strong&gt;develop a 2D Game in Go&lt;/strong&gt;, which, by the way, I agree with her that is a fun way to learn Go. In fact, I actually started a long time ago a very small console game &lt;a href="https://github.com/mcaci/wallrush"&gt;wallrush&lt;/a&gt;, with the excuse of practising Go with a fun project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w_LHvU4q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5ilb8ymggypv4tg9y0o.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w_LHvU4q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5ilb8ymggypv4tg9y0o.jpeg" alt="Drishti Jain on how to develop a 2D Game in Go" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Drishti Jain on how to develop a 2D Game in Go&lt;/b&gt;



&lt;p&gt;There are so many other things I could mention but this could get extremely long, so we'll move to the next topic, but not before a quick mention to the &lt;strong&gt;TinyGlobo 2&lt;/strong&gt; &lt;a href="https://twitter.com/deadprogram/status/1674002660016500736"&gt;launch&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go-ing to next level
&lt;/h2&gt;

&lt;p&gt;This topic is the trickiest to describe but I'll make my best to convey what I took out from this with these two examples.&lt;/p&gt;

&lt;p&gt;The first one is related to the workshop of &lt;strong&gt;Bill Kennedy&lt;/strong&gt; about &lt;strong&gt;Ultimate Services in Kubernetes&lt;/strong&gt; where he shared several tips and trick to both create an application and deploy it in Kubernetes and to take well known Go concepts and take them to the next level.&lt;br&gt;
Some of these ideas are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have a deploy-first mentality: prepare your deployment with all the configuration you need and a minimal code to support it. Once your minimal application is deployed in the cluster you can concentrate on the business logic&lt;/li&gt;
&lt;li&gt;Think about the package as an API, which creates firewalls between code sections as it can only be accessed via its exported symbols. Also if a package is an API, it serves by providing functionalities, not by containing them, which is a very important distinction between a functional package and a package that just serves as a bin containing things we might forget&lt;/li&gt;
&lt;li&gt;Start by accepting data for what it is and then discover what it does (concrete type vs interface).&lt;/li&gt;
&lt;li&gt;Consider that errors are handled when acknowledged or treated in some way, for example by logging them. Once handled, the error should not be propagated any further.&lt;/li&gt;
&lt;li&gt;Prefer to not deal with errors inside an &lt;code&gt;http.Handler&lt;/code&gt; but make sure that you create an Handler with a function that returns an error so that it can be handled in every situation, e.g. by defining a &lt;code&gt;type Handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) error&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rMZOiRrs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gw8r1r4w4g9znsgahbrj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rMZOiRrs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gw8r1r4w4g9znsgahbrj.jpeg" alt="Bill Kennedy at the Ultimate Services workshop" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Bill Kennedy at the Ultimate Services workshop&lt;/b&gt;



&lt;p&gt;These are just few examples where I noticed something clicking in my head, I really tried to see through the examples given during the workshop and I'm convinced that I need to give a try myself to understand it better and assimilate these concepts as well.&lt;/p&gt;

&lt;p&gt;The second example, I think of, is the talk done by &lt;strong&gt;Julien Cretel&lt;/strong&gt; about how to create and use &lt;strong&gt;functional options&lt;/strong&gt; during the creation of values from a structure. This idea is not new because it exploits a lot the concept in Go of &lt;em&gt;functions as first class citizens&lt;/em&gt;, but it is also not easy to put in place as it requires some understanding in how to use functions to configure the values of a field. The fact of going from &lt;code&gt;func New(/* parameters with values to assign to MyStruct fields*/) *MyStruct&lt;/code&gt; to &lt;code&gt;func New(opts ...func(*MyStruct)) *MyStruct&lt;/code&gt; is just the first step to help create values in a cleaner way that goes beyond simple "Constructor functions" or "Configuration structures". In his talk, however Julien didn't just explain how to create functional options but also when and how to use them to make sure that we can get the best of their implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The importance of security
&lt;/h2&gt;

&lt;p&gt;Security is one of the pillar of today's focus when developping an application, as more often than not, attacks uncover the vulnerabilities that affect it or the libraries on which it depends on.&lt;/p&gt;

&lt;p&gt;Go is not undervaluing the security efforts and this was highlighted in both keynotes: the aformentioned one by &lt;strong&gt;Cameron Balahan&lt;/strong&gt; about the the &lt;strong&gt;state of Go&lt;/strong&gt; and the one focusing on &lt;strong&gt;vulnerability management&lt;/strong&gt; in Go by &lt;strong&gt;Julie Qiu&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If we focus first on the keynote from Julie Qiu, the manager of the security team in Go, it was important to hear about the meaning of vulnerability and how they can affect the supply chain (by actually using a very tasty cake analogy 😄🍰). To address this the go team worked on several layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tooling&lt;/li&gt;
&lt;li&gt;data&lt;/li&gt;
&lt;li&gt;documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;tooling&lt;/strong&gt; has seen the introduction of the &lt;code&gt;vulncheck&lt;/code&gt; command, just &lt;a href="https://twitter.com/golang/status/1679528457846378496"&gt;recently&lt;/a&gt; released, that helps to identify security issues inside the dependencies of a Go module with an effort to reduce the noise and convey only the important information in order to fix the most urgent security issue. The vulncheck tool also sees it's first integration int he CI thanks to the appropriate Github Action that has been implemented to include it in a CI build for a Go application.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;data&lt;/strong&gt; is taken care thanks to the &lt;a href="https://vuln.go.dev"&gt;vulnerability database&lt;/a&gt;, which provides a comprehensive source of information about known vulnerabilities in public Go modules, which in turn are shown in the &lt;strong&gt;documentation&lt;/strong&gt; that will display a sign if there has been a vulnerability detected inside the package page in .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bvas9lDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rn2rf8smw37pcpttb4z.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bvas9lDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rn2rf8smw37pcpttb4z.jpeg" alt="Julie Qiu on how to manage vulnerabilities" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Julie Qiu on how to manage vulnerabilities&lt;/b&gt;



&lt;p&gt;These information go to support the story behind the state of Go which is not just a language that is growing with time but also a full consolidating ecosystem that is designed to be a productive and production-ready platform. For this reason it is not only important that Go is easy to learn to get onboarded, but also that it comes with its own tools to perform many operations, like testing, benchmarks, module management, fuzzing and vulnerability checking (to name a few) that make the base for the creation of stable, secure, reliable and efficient applications with Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  A personal note
&lt;/h2&gt;

&lt;p&gt;GopherConEU 2023 was not just for me a place where I heard interesting talks and topics about my favorite programming language.&lt;/p&gt;

&lt;p&gt;It was for sure an occasion to meet a lot of nice Gophers, old and new, chat with them and share our experiences. Be it with the Go team or with the other Gophers it was nice to share my projects like &lt;a href="https://github.com/mcaci/wallrush"&gt;wallrush&lt;/a&gt; and the Go &lt;a href="https://github.com/mcaci/lets-go-workshop"&gt;workshop&lt;/a&gt; I presented at &lt;a href="https://rivieradev.fr/"&gt;RivieraDEV&lt;/a&gt; or my experience to help the organization of RivieraDEV and at the same time hear about the others and see what they were working on both on the professional side and on the free time.&lt;/p&gt;

&lt;p&gt;Speaking of personal projects one stood out during the conference and it was &lt;a href="https://github.com/mcaci/gopherconeu23img"&gt;gopherconeu23img&lt;/a&gt;. Why was it so special? It's because, it's a CLI, totally written in Go, that creates GIFs in ASCII art from an input text and, most importantly, it was used to create some of the GIFs that were included in the slides of this year's edition of GopherConEU. 😍&lt;/p&gt;

&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/carstencodes/status/1674328086509154305"&gt;Welcome Back&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/AleInTech/status/1674040288145207308"&gt;Lunch Break&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/goMicheleCaci/status/1680272723694551040"&gt;The Lunch Break gif in action&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another thing I want to mention is &lt;strong&gt;Giuseppe Scaramuzzino&lt;/strong&gt;'s &lt;a href="https://twitter.com/webdeva/status/1674412124427149312"&gt;lightning talk&lt;/a&gt; &lt;strong&gt;Unleashing Desktop App Development with Go and Fyne&lt;/strong&gt; which was great, informative and very well received by the audience. I'm proud he was selected to perform his talk and to have played a small part on his decision to submit this talk. Great job! 😎&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pJq_9ZP5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1coq52oqymhlkzolko0f.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pJq_9ZP5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1coq52oqymhlkzolko0f.jpeg" alt="Giuseppe's Lightning talk about Fyne" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Giuseppe's Lightning talk about Fyne&lt;/b&gt;



&lt;h2&gt;
  
  
  Parting thoughts
&lt;/h2&gt;

&lt;p&gt;The idea of this article was not to be exactly a report on the talks of GopherConEU 2023 as there are some good reports out there that highlight well the content of the talks. The idea was to highlight some thoughts on the state of Go and its community after meeting all the Gophers in person and hearing the content of the talks proposed during the conference.&lt;/p&gt;

&lt;p&gt;It's a bit of a pity that I might not be able to attend to the other editions of GopherCon (a baby 👶 is coming, so unless I'm talking I prefer to attend remotely where possible) this year but I hope that these thoughts will be confirmed and some new ones will get the spotlight.&lt;/p&gt;

&lt;p&gt;GopherCon EU was not just an occasion for sharing and learning, it was also a moment of distention and entertainement, I'm thinking especially of the social mixer after the first day of conference and the live episode of Go Time podcast with a session of the "Gopher Say" quiz game. If you haven't had the chance to participate, the talks will be made available in YouTube, so at some point you'll be able to access the content as well.&lt;/p&gt;

&lt;p&gt;I will close again by thanking everyone that made this edition of GopherConEU and sharing some more pictures of this two days marathon.&lt;/p&gt;

&lt;p&gt;You can find me up on &lt;a href="https://www.linkedin.com/in/michele-caci-47770132/"&gt;linkedin&lt;/a&gt;, &lt;a href="//github.com/mcaci"&gt;github&lt;/a&gt; and twitter at &lt;a href="//twitter.com/goMicheleCaci"&gt;@goMicheleCaci&lt;/a&gt; or here on dev.to &lt;a class="mentioned-user" href="https://dev.to/mcaci"&gt;@mcaci&lt;/a&gt; and I'm looking forward to hearing your comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This was Michele and thanks for reading!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kbsB1xRr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tuo3tnhk5luy8r1wf1i9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kbsB1xRr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tuo3tnhk5luy8r1wf1i9.jpeg" alt="The queue for the workshop day" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;The queue for the workshop day&lt;/b&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NMc8YyaH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2oju7o1c20dee76jsyu2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NMc8YyaH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2oju7o1c20dee76jsyu2.jpeg" alt="Panel with the Go team" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Panel with the Go team&lt;/b&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5hRwRKOm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tkkh34sm88rt9pd7o9bc.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5hRwRKOm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tkkh34sm88rt9pd7o9bc.jpeg" alt="Some of the GopherConEU Swag" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Some of the GopherConEU Swag&lt;/b&gt;



</description>
      <category>go</category>
      <category>gophercon</category>
    </item>
    <item>
      <title>My GoLab 2022 experience</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Fri, 14 Oct 2022 21:01:56 +0000</pubDate>
      <link>https://dev.to/mcaci/my-golab-2022-experience-5e1p</link>
      <guid>https://dev.to/mcaci/my-golab-2022-experience-5e1p</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--867vV0P0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hr0pkqu4pzm1aj2qzuzh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--867vV0P0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hr0pkqu4pzm1aj2qzuzh.jpg" alt="Golab2022" width="880" height="663"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Laptop courtesy of my sweet wife&lt;/b&gt;



&lt;p&gt;Last week the 2022 edition of GoLab 2022 happened and I wish to share with you my experience for the two days of conference that I attended and share my view of the different talks that were presented.&lt;/p&gt;

&lt;p&gt;This edition was special as the equivalent conference for Rust, RustLab, was also organized at the same moment, but more on this soon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: The idea to have GoLab and RustLab together was nice as it encouraged people with different view and experiences to meet and share. On the GoLab side there were a lot of interesting talks and people to speak with, I really enjoyed it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's start
&lt;/h2&gt;

&lt;p&gt;Golab 2022 was composed of several days of events: the first day was the one for the workshops and the two following days were the conference days. I just participated to the two days of talks but it was already a good way to &lt;strong&gt;meet as many Gophers and share ideas and knowledge about Go&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This edition of GoLab was organized by &lt;a href="https://www.develer.com/en/"&gt;Develer&lt;/a&gt; just outside the city of Florence in Italy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yrvhGAeq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4hzsw562sysvvuag32zv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yrvhGAeq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4hzsw562sysvvuag32zv.jpg" alt="Lets start" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Let's start&lt;/b&gt;



&lt;h2&gt;
  
  
  About the conference
&lt;/h2&gt;

&lt;p&gt;I want to share the content of these two days of conference by building around a few concepts that I think well summarize the content of what was shared during the conference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Going beyond the simplicity&lt;/li&gt;
&lt;li&gt;Go outside of Go&lt;/li&gt;
&lt;li&gt;Striving towards security&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Going beyond the surface
&lt;/h3&gt;

&lt;p&gt;Some of the talks of these two days focused on going behind the surface of Go either by showing some &lt;em&gt;obscure&lt;/em&gt; language behaviors or by exploring the standard library. One of the biggest highlight of this section is that most of the time the &lt;a href="https://go.dev/doc/"&gt;Go documentation&lt;/a&gt; provide explanations about these behaviors or well explains the &lt;a href="https://pkg.go.dev/"&gt;packages&lt;/a&gt; even though they are not consulted until needed.&lt;/p&gt;

&lt;p&gt;This was reflected, for example, in the talk about the things you didn't know about Go by &lt;a href="https://twitter.com/empijei"&gt;Roberto Clapis&lt;/a&gt; where he gave a deep view on the internals of Go and some very unexpected behaviors in a very entertaining way. He showed us also that the explanation for these unexpected behaviors can often be found in the Go documentation which provides a precious resource to consult at any time of need.&lt;/p&gt;

&lt;p&gt;In this context I would also highlight the talks of &lt;a href="https://twitter.com/bstncartwright"&gt;Boston Cartwright&lt;/a&gt; about the sql package and the driver pattern of &lt;a href="https://twitter.com/fedepaol"&gt;Federico Paolinelli&lt;/a&gt; where he gave some practical tips on which constructs and syntax elements to use to write Go code that is simple to read and maintain. From these talks, I took away the contrast between the &lt;strong&gt;simplicity that Go offers to developers&lt;/strong&gt; with the &lt;strong&gt;complexity inside the language&lt;/strong&gt; that makes it possible to be simple to use.&lt;/p&gt;

&lt;p&gt;This in a way is summed up in a &lt;a href="https://www.youtube.com/watch?v=rFejpH_tAHM&amp;amp;ab_channel=dotconferences"&gt;talk&lt;/a&gt; given by Rob Pike about the complexity that makes Go simple to use: &lt;em&gt;"Simplicity is Complicated"&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go outside of Go
&lt;/h3&gt;

&lt;p&gt;One of the recurrent topics during these two days where the usage of Go outside of the plain language itself and especially I think of two specific cases: the usage of Go in microservices and the integration of C and Go with the &lt;strong&gt;cgo&lt;/strong&gt; feature.&lt;/p&gt;

&lt;p&gt;On the microservice side there was a nice talk given by &lt;a href="https://twitter.com/classic_addetz"&gt;Adelina Simion&lt;/a&gt; and Arthur Kondas about communication between microservices where they gave useful tips about when and how to go from a monolith to microservices while also sending very positive vibes from the stage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LYA1eA-X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5icf6z8g6fcbywuumfb2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LYA1eA-X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5icf6z8g6fcbywuumfb2.jpg" alt="Technical problems are no problems" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Technical problems are no problems&lt;/b&gt;



&lt;p&gt;On the cgo side I want to highlight two talks: one from &lt;a href="https://twitter.com/croloris"&gt;Loris Cro&lt;/a&gt; about dealing with cross-compilation difficulties, that the usage of cgo brings, using the Zig language and the other from &lt;a href="https://twitter.com/jasondellaluce"&gt;Jason Dellaluce&lt;/a&gt; and &lt;a href="https://twitter.com/leogrease"&gt;Leonardo Grasso&lt;/a&gt; about how to extend &lt;a href="https://falco.org/"&gt;Falco&lt;/a&gt;, a Kubernetes threat detection engine, which is written in C++, with plugins written in Go, explaining the challenges of integrating cgo in both C and Go.&lt;/p&gt;

&lt;p&gt;It was very interesting to me to see how &lt;strong&gt;Go can introduce its way&lt;/strong&gt; through various projects and architectures making it a viable language in contexts where other mainstream languages, like C++, Java or Python, used to be the main languages of choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Striving towards security
&lt;/h3&gt;

&lt;p&gt;For sure one of the big topic of the conference was the security around Go, the main argument being that security is built-in Go thanks to the standard library for example with the &lt;a href="https://pkg.go.dev/crypto"&gt;crypto&lt;/a&gt; package or thanks to the &lt;a href="https://go.dev/security/fuzz/"&gt;fuzzying&lt;/a&gt; feature that was recently introduced with Go version 1.18.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TnMGs41R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zvrhxt8jy96t47qgd94l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TnMGs41R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zvrhxt8jy96t47qgd94l.jpg" alt="Filippo speaking about the crypto package" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Filippo speaking about the crypto package&lt;/b&gt;



&lt;p&gt;In this context I want to highlight the talks of &lt;a href="https://twitter.com/FiloSottile"&gt;Filippo Valsorda&lt;/a&gt; where he explained how is security managed and tested inside Go's &lt;em&gt;crypto&lt;/em&gt; package, the talk from &lt;a href="https://twitter.com/sagarsonwane23"&gt;Sagar Sonwane&lt;/a&gt; with an entertaining and clear introduction to &lt;em&gt;fuzzying&lt;/em&gt; and the talk from &lt;a href="https://twitter.com/mvdan"&gt;Daniel Marti&lt;/a&gt; where he explained us what techniques of defensive programming we can make use of to defend from unforeseen, and potentially dangerous, usages of our code.&lt;/p&gt;

&lt;p&gt;This is not the first time that security in Go is highlighted in a conference but it was good to see the message about security reinforced with more insights and practical information that us gophers can use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting thoughts
&lt;/h2&gt;

&lt;p&gt;I could go on speaking and detailing about all the talks that were given as they were all interesting and insightful but I would never end writing my thoughts.&lt;/p&gt;

&lt;p&gt;In the end, GoLab was not just an occasion for sharing and learning, it was also a moment of entertainment and meeting with new people in a friendly environment and If you haven't had the chance to participate, the best way to learn more about the content will be to watch the talks when they will be made available on YouTube.&lt;/p&gt;

&lt;p&gt;I will close again by &lt;strong&gt;thanking everyone&lt;/strong&gt; that made this edition of Golab possible and sharing some more pictures of the conference.&lt;/p&gt;

&lt;p&gt;You can find me up on twitter &lt;a href="https://twitter.com/nikiforos_frees"&gt;@nikiforos_frees&lt;/a&gt; or here on dev.to &lt;a class="mentioned-user" href="https://dev.to/mcaci"&gt;@mcaci&lt;/a&gt; and I'm looking forward to hearing your comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This was Michele, thanks for reading!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q7bDGaJO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvr8vt60hoe0lcby52lq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q7bDGaJO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvr8vt60hoe0lcby52lq.jpg" alt="At the conference venue" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;At the conference venue&lt;/b&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TajG-YQV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a41yavr7tb8plq0hnmut.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TajG-YQV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a41yavr7tb8plq0hnmut.jpg" alt="Daniel Marti explaining defensive programming" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Daniel Marti explaining defensive programming&lt;/b&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1jg33j4r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/krx8iujaa7mcms6z1kiv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1jg33j4r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/krx8iujaa7mcms6z1kiv.jpg" alt="Closing the conference with a twilight over Florence" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Closing the conference with a twilight over Florence&lt;/b&gt;



</description>
      <category>go</category>
      <category>golab</category>
    </item>
    <item>
      <title>My GopherConEU 2022 experience</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Wed, 10 Aug 2022 05:30:44 +0000</pubDate>
      <link>https://dev.to/mcaci/my-gopherconeu-2022-experience-114i</link>
      <guid>https://dev.to/mcaci/my-gopherconeu-2022-experience-114i</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0kl6An6R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ip1067ke7iuo4ky99vur.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0kl6An6R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ip1067ke7iuo4ky99vur.jpeg" alt="GopherConEU2022" width="880" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A week has already passed since GopherConEU 2022, held in July 28th to 31st, and I wish to share with you my experience of these amazing conference days and my take of the content of what was said in the various talks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: it was great to be back in person, meet new Gophers, hearing a lot of interesting talks and I was very happy to be speaking to a live audience for the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's start
&lt;/h2&gt;

&lt;p&gt;GopherConEU 2022 was composed of several days: a community event, the workshop day and a two days run of talks. My participation was limited to the two days of talks but I sure felt the &lt;strong&gt;great energy and friendly atmosphere&lt;/strong&gt; that sourrounds the Go community. Everyone was eager to exchange and learn about Go, either on specific topics or on the general trends.&lt;/p&gt;

&lt;p&gt;Every edition of GopherConEU, this being the 5th, has been organized in a different location, Iceland and the Canary islands to name a few; this year's edition was organized in Berlin in the Festsaal Kreuzberg.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DBHhe8Kj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8s5j3wf70oy1vct2i9cy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DBHhe8Kj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8s5j3wf70oy1vct2i9cy.jpg" alt="Lets start" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Let's start&lt;/b&gt;



&lt;h2&gt;
  
  
  A summary of two days
&lt;/h2&gt;

&lt;p&gt;I'm going to build the resume of I took away from the talks of these two-days conference by discussing around these elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Embracing the simplicity&lt;/li&gt;
&lt;li&gt;A focus on memory&lt;/li&gt;
&lt;li&gt;Practical uses of Go&lt;/li&gt;
&lt;li&gt;The Go team&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Embracing the simplicity
&lt;/h3&gt;

&lt;p&gt;Some of the talks of these two days highlighted the &lt;strong&gt;simplicity&lt;/strong&gt; of the Go language by looking at the experiences that the speakers had with their work and with some references to the &lt;a href="https://en.wikipedia.org/wiki/Unix_philosophy"&gt;UNIX philosophy&lt;/a&gt; of building modular, simple and transparent software.&lt;/p&gt;

&lt;p&gt;This was reflected, for example, in the talk about CLIs in Go by &lt;a href="https://twitter.com/mmontagnino"&gt;Marian Montagnino&lt;/a&gt; where she gave a lot of insights on how to make a CLI that feels closer to the user than to the machine; in the talk about making the service easier to extend and refactor by transforming it into a platform by &lt;a href="https://twitter.com/konradreiche"&gt;Konrad Reiche&lt;/a&gt;. In this one in particular the focus was in making the distinction between eventual complexity, that is intrinsic to the problem we want to solve, and accidental complexity, which is the one we introduce while solving a a problem, and his experience showed us a way to reduce the accidental complexity; and as well another in the talk given by &lt;a href="https://twitter.com/egonelbre"&gt;Egon Elbre&lt;/a&gt; that gave really useful tips about how (and when) to use concurrency, by showing patterns and constructs that are safer and simpler to use when introducing concurrency in our applications.&lt;/p&gt;

&lt;p&gt;And last but not least, the talk by &lt;a href="https://twitter.com/YardenLaif"&gt;Yarden Laifenfeld&lt;/a&gt; where she shared her experience of migrating an application from an OOP language (Java) to Go and we reinforced the message that when going from a language to Go (or any other language) it is never a plain translation, but an &lt;strong&gt;embracement of Go values and features&lt;/strong&gt;, because they are too different from one language to another and this holds very true when thinking of Java and Go.&lt;/p&gt;

&lt;p&gt;This to me highlights the experiences of the Go community when striving in making things simple, as said in the &lt;a href="https://go-proverbs.github.io/"&gt;Go Proverb&lt;/a&gt; &lt;em&gt;"Clear is better than clever"&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A focus on memory
&lt;/h3&gt;

&lt;p&gt;A lot of discussions were made around the memory and resources usage: from the talk about the new &lt;a href="https://tip.golang.org/doc/go1.19#runtime"&gt;memory limit&lt;/a&gt; feature coming with Go 1.19 explained to us by &lt;a href="https://twitter.com/mknyswe"&gt;Michael Knyszek&lt;/a&gt; to the entertaining story about a feud between &lt;a href="https://twitter.com/goinggodotnet"&gt;Bill Kennedy&lt;/a&gt; and a man named Tyler about the memory allocations done by their algorithms and some practical tips how to use &lt;em&gt;pprof&lt;/em&gt; to investigate the performances and reduce the resources usage and when it's really worth doing it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wOf4xxI7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j5j3ktx2k5iir74beiyf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wOf4xxI7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j5j3ktx2k5iir74beiyf.jpg" alt="Bill Kennedy on memory profiling" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Bill Kennedy on memory profiling&lt;/b&gt;



&lt;p&gt;This was very interesting in a context where we want take care of our consumptions to see how to check what we consume and where we can do better and in &lt;strong&gt;which situations it is important (or not) to do it&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical uses of Go
&lt;/h3&gt;

&lt;p&gt;Many of the talks were also about how the community has used Go in its own projects.&lt;/p&gt;

&lt;p&gt;Some of the highlights in this regard were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The talk about the usage of &lt;a href="https://tinygo.org/"&gt;TinyGo&lt;/a&gt; to check the environment inside the hen house of &lt;a href="https://twitter.com/doniacld"&gt;Donia Chaiehloudj&lt;/a&gt; where she made use of TinyGo to create an application embedded in an integrated circuit that took some measures and sent them to Grafana.&lt;/li&gt;
&lt;li&gt;The talk by &lt;a href="https://twitter.com/lostluck"&gt;Robert Burke&lt;/a&gt; about how to use Apache Beam, now supporting Go, to perform stream processing in our applications, to consider the difference between event time and processing time and especially to focus on windows of event times instead of the event time itself.&lt;/li&gt;
&lt;li&gt;The talk by &lt;a href="https://twitter.com/akwickert"&gt;Anna-Katharina Wikert&lt;/a&gt; where she explained us how to follow the vulnerable parts of our code from the source, e.g. sensitive data, to a potential sink, e.g. a &lt;code&gt;log.Println&lt;/code&gt; statement without any sanitization process, using the &lt;a href="https://github.com/google/go-flow-levee"&gt;go-flow-levee&lt;/a&gt; tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I could go on speaking and detailing about all the talks that were given as they were all interesting and insightful but I would never end my speech so let's move to...&lt;/p&gt;

&lt;h3&gt;
  
  
  The Go team
&lt;/h3&gt;

&lt;p&gt;There were few interactions with the Go team, besides the talk of Michael about memory limits, that were centered on a panel with the Go team where people could ask questions to some members of the Go team, Than Macintosh, &lt;a href="https://twitter.com/cameronbalahan"&gt;Cameron Balahan&lt;/a&gt;, Michael Knyszek and on some reflections shared by Cameron on how Go has become the Go we love today.&lt;/p&gt;

&lt;p&gt;Some of the highilghts I took away were around the history of Go, how it grew by &lt;strong&gt;embracing the community&lt;/strong&gt; via the feedbacks from the surveys and the github issues and how it maintained its importance by &lt;strong&gt;embracing the enterprise&lt;/strong&gt; by brainstorming around ideas that could help enterprises adopt Go more easily and how it keeps &lt;strong&gt;evolving&lt;/strong&gt; besides language features, e.g. in its toolset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xVy0xGTT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvk79w5aly239j1afcp8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xVy0xGTT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvk79w5aly239j1afcp8.jpg" alt="How Go became its best self" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;How Go became its best self&lt;/b&gt;



&lt;p&gt;&lt;em&gt;"No is the the default answer"&lt;/em&gt; is a sentence shared by the Go team to convey in a very effective way the fact that Go's values are simplicity and stability; this is in comparison to other languages that may add new features more frequently and make them sometimes more complex and challenging to embrace.&lt;/p&gt;

&lt;p&gt;A last interesting point, shared by the Go team, was again about security as the evolution of Go keeps growing around functionalites and tools that help for instance with the dependency checks, e.g. the tampering check on the &lt;code&gt;go.sum&lt;/code&gt; in Go modules and the introduction of &lt;strong&gt;fuzzing&lt;/strong&gt; to help unit test our application to find potentially dangerous edge cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  A personal note
&lt;/h2&gt;

&lt;p&gt;GopherConEU 2022 was not just for me a place where I heard interesting talks and topics about my favorite language.&lt;/p&gt;

&lt;p&gt;First of all it was an &lt;strong&gt;occasion to meet a lot of nice Gophers&lt;/strong&gt; from all over Europe, exchange and share our experences with them. There I met, for instance, nice people from Arduino, people from Celltech using Go to work on the creation and testing of batteries and other nice companies using Go for many different projects from Finance and Payment (Upvest and Form3) to Food Delivery (Delivery Hero), Data Federation (Hygraph) and Marketing and App promotion (Remerge).&lt;/p&gt;

&lt;p&gt;Then, this edition of GopherConEU was special to me because it was my &lt;strong&gt;first experience of talking in public to a live audience&lt;/strong&gt;. My talk was the second lightning talk where I did a small live coding session to show the power of the standard library when it comes to take the first steps to develop a web application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KjVP5weT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6nadq9simth6kjcyxyx.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KjVP5weT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6nadq9simth6kjcyxyx.jpeg" alt="My first live talk" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;My first live talk 😍&lt;/b&gt;

 

&lt;p&gt;First live talk + lightning talk + live coding = a lot of challenge.&lt;/p&gt;

&lt;p&gt;And a challenge was what I wanted to propose, to myself, to the organizers and to the audience, if selected. I must admit I was a bit nervous when I proposed it, but as I got accepted it was time to take on this challenge!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/f8TXO6yBb8CgU/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/f8TXO6yBb8CgU/giphy.gif" alt="Challenge accepted" width="400" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And so it happened!&lt;/p&gt;

&lt;p&gt;For this I must thank all the organization of the GopherConEU, from &lt;a href="https://twitter.com/NataliePis"&gt;Natalie&lt;/a&gt; to Donna and everyone involved to give me this opportunity and honor and also a big thanks to the co-hosts &lt;a href="https://twitter.com/matryer"&gt;Mat Ryer&lt;/a&gt; and &lt;a href="https://twitter.com/veekorbes"&gt;V Korbes&lt;/a&gt; that supported and encouraged me before going on the stage.&lt;/p&gt;

&lt;p&gt;Should you want to know more about this talk you can check my &lt;a href="https://github.com/mcaci/websvc"&gt;websvc&lt;/a&gt; repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting thoughts
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9f5tf-wg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iirztl434coidh5p8emb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9f5tf-wg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iirztl434coidh5p8emb.jpeg" alt="What we do on Sunday" width="720" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;We sure were! 😁&lt;/b&gt;

 

&lt;p&gt;GopherCon EU was not just an occasion for sharing and learning, it was also a moment of distention and entertainement, I'm thinking especially of the improvised talks given by Mat Ryer and V Korbes on subjects given by the attendees (testing and doing code review with people you don't like) and a Live Episode of &lt;a href="https://changelog.com/gotime"&gt;Go Time&lt;/a&gt; podcast with the "Gopher Say" Game.&lt;/p&gt;

&lt;p&gt;Again, there are so many things that are worth mentioning but time is running out. If you haven't had the chance to participate to GopherCon EU, the talks will be made available in YouTube at some point you'll be able to do it soon.&lt;/p&gt;

&lt;p&gt;I will close again by &lt;strong&gt;thanking everyone&lt;/strong&gt; that made this edition of GopherConEU and sharing some more pictures of this two days marathon.&lt;/p&gt;

&lt;p&gt;You can find me up on twitter &lt;a href="https://twitter.com/nikiforos_frees"&gt;@nikiforos_frees&lt;/a&gt; or here on dev.to &lt;a class="mentioned-user" href="https://dev.to/mcaci"&gt;@mcaci&lt;/a&gt; and I'm looking forward to hearing your comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This was Michele, thanks for reading!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EDIT&lt;/strong&gt;: The &lt;a href="https://www.youtube.com/watch?v=JDRPfIlNqEs&amp;amp;ab_channel=GopherConEurope"&gt;video&lt;/a&gt; for my lightning talk has been published! I hope you enjoy it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q_xzztaD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ow1fiqt3vm9lolz79op.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q_xzztaD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ow1fiqt3vm9lolz79op.jpg" alt="Gopher say" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7MH6H0Pv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hupu54y057499q2bqmsx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7MH6H0Pv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hupu54y057499q2bqmsx.jpg" alt="Saturday's Party" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vmTVNMNE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aglcjrblbpdxqnmylytu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vmTVNMNE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aglcjrblbpdxqnmylytu.jpg" alt="Gopher Graffiti" width="880" height="1564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hM7oxDz_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34plsj7lym85o2wp60u9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hM7oxDz_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34plsj7lym85o2wp60u9.jpg" alt="Bye GopherConEU" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>gopherconeu</category>
    </item>
    <item>
      <title>TIL: How to listen to different servers in Go (using select)</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Mon, 25 Apr 2022 17:48:09 +0000</pubDate>
      <link>https://dev.to/mcaci/til-how-to-listen-to-different-servers-in-go-using-select-566m</link>
      <guid>https://dev.to/mcaci/til-how-to-listen-to-different-servers-in-go-using-select-566m</guid>
      <description>&lt;p&gt;Today I learned how to listen to different servers in Go by refactoring an existing codebase of mine. The goal of this refactoring was to correctly use &lt;code&gt;select&lt;/code&gt; statement instead of creating an &lt;em&gt;"artificial"&lt;/em&gt; one.&lt;/p&gt;

&lt;p&gt;This is the starting point: I'm omitting most of the code to best highlight the &lt;em&gt;"artificial"&lt;/em&gt; select that was present at the beginning of my refactoring.&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;func&lt;/span&gt; &lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c"&gt;/* options here*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGTERM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&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;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="c"&gt;// [...]&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;startHTTPSrv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errChan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// [...]&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;startGRPCSrv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errChan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// [...]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;errChan&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;startHTTPSrv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// the param list is simplified to focus only on the err chan&lt;/span&gt;
    &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c"&gt;/* http.ListenAndServe params */&lt;/span&gt;&lt;span class="p"&gt;)&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;startGRPCSrv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// the param list is simplified to focus only on the err chan&lt;/span&gt;
    &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;gRPCServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c"&gt;/* gRPCServer.Serve params */&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;Since the same &lt;code&gt;errChan&lt;/code&gt; is used everywhere, any of the goroutines that ends up returning an error, be it the HTTP server, the GRPC one or the SIGINT/SIGTERM listener, will make the &lt;code&gt;Start&lt;/code&gt; func exit.&lt;/p&gt;

&lt;p&gt;This is actually the behaviour of a &lt;code&gt;select&lt;/code&gt; statement; which is why I started transforming it and this is how it looks now.&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;func&lt;/span&gt; &lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;startHTTPSrv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newSrvData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPAddr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;startGRPCSrv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newSrvData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GRPCAddr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;handleSigTerm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&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;func&lt;/span&gt; &lt;span class="n"&gt;startHTTPSrv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c"&gt;/* params */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// the param list is simplified to focus only on the err chan&lt;/span&gt;
    &lt;span class="c"&gt;// [...]&lt;/span&gt;
    &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c"&gt;/* http.ListenAndServe params */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errChan&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;startGRPCSrv&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="c"&gt;/* params */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// the param list is simplified to focus only on the err chan&lt;/span&gt;
    &lt;span class="c"&gt;// [...]&lt;/span&gt;
    &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// [...]&lt;/span&gt;
        &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;gRPCServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c"&gt;/* gRPCServer.Serve params */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errChan&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;handleSigTerm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// [...]&lt;/span&gt;
    &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGTERM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;errChan&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&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;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errChan&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the usage of the &lt;code&gt;select&lt;/code&gt; statement is able to show the clear distinction between the different goroutines run and wait for the first one to exit to return from &lt;code&gt;Start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Besides the change in the &lt;code&gt;Start&lt;/code&gt; func, the other functions have also been changed to return a receiver &lt;code&gt;chan&lt;/code&gt; of errors instead of a plain error in order to be comfortably used inside the select statement.&lt;/p&gt;

&lt;p&gt;There are two positive aspects in this refactor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It gives a good showcase for the usage of the select statement to listen to different processes/servers.&lt;/li&gt;
&lt;li&gt;It shows a way to transition from an "artificial" select statement to an idiomatic one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope this was helpful, thanks a lot for your time reading it!&lt;/p&gt;

&lt;p&gt;p.s. &lt;a href="https://github.com/mcaci/briscola-serv/commit/010d0fb5e95fff4d07db03b5eb73193276967aad?diff=split"&gt;Here be dragons!&lt;/a&gt; A.k.a the github reference for the commit I did with the complete change that inspired this TIL.&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>go</category>
      <category>select</category>
    </item>
    <item>
      <title>TIL: Go range on time.Tick for regular tasks </title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Thu, 26 Aug 2021 15:46:02 +0000</pubDate>
      <link>https://dev.to/mcaci/til-go-range-on-time-tick-for-regular-tasks-4lid</link>
      <guid>https://dev.to/mcaci/til-go-range-on-time-tick-for-regular-tasks-4lid</guid>
      <description>&lt;p&gt;Today I learned how to simply repeat a task over time with regularity in Go:&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;for&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, playground"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// any task here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a playground example in action: &lt;a href="https://play.golang.org/p/RUdgii5EMx7"&gt;https://play.golang.org/p/RUdgii5EMx7&lt;/a&gt;&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>go</category>
      <category>tick</category>
    </item>
    <item>
      <title>TIL: Find alone and find within loops in a shell</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Mon, 19 Apr 2021 16:51:00 +0000</pubDate>
      <link>https://dev.to/mcaci/til-find-alone-and-find-within-loops-in-a-shell-2k36</link>
      <guid>https://dev.to/mcaci/til-find-alone-and-find-within-loops-in-a-shell-2k36</guid>
      <description>&lt;p&gt;Today I learned a situation in which is good to use a &lt;strong&gt;for loop&lt;/strong&gt; in a shell in moments when the &lt;strong&gt;-exec&lt;/strong&gt; flag alone is difficult to use.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;find&lt;/strong&gt; command in any case is very powerful and can assist in many shell tasks. Usually when executing commands on a set of file the &lt;code&gt;find&lt;/code&gt; command, together with the &lt;code&gt;-exec&lt;/code&gt; expression in the &lt;code&gt;find $PATH -exec $COMMAND {} \;&lt;/code&gt; instruction, is very useful to write short and meaningful operations like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find ./ &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="nv"&gt;$PATTERN&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to print the content of a list of files denoted by the &lt;em&gt;PATTERN&lt;/em&gt; variable.&lt;/p&gt;

&lt;p&gt;However, it is not very useful when the situation gets complex like in this scenario.&lt;/p&gt;

&lt;p&gt;Suppose we have 2 files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;file1&lt;/em&gt; with content&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;-l&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;file2&lt;/em&gt; with content&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;-a&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And we want to run &lt;code&gt;ls&lt;/code&gt; with the options found in these files.&lt;/p&gt;

&lt;p&gt;In this context the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find ./ &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"file*"&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;would not work (the error would be "&lt;em&gt;cat: {}: No such file or directory&lt;/em&gt;").&lt;/p&gt;

&lt;p&gt;In this situation a classic &lt;strong&gt;for range&lt;/strong&gt; loop will help us achieve this goal. As in this example&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="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;find ./ &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"file*"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Despite being very unconventional uses of those instructions, I propose these examples to draw a line on where the &lt;code&gt;find&lt;/code&gt; command manages to do the job alone and where it is more helpful to include its resuls it in a &lt;code&gt;for range&lt;/code&gt; loop.&lt;/p&gt;

&lt;p&gt;Hope this was helpful, thanks a lot for your time reading it!&lt;/p&gt;

</description>
      <category>shell</category>
      <category>find</category>
      <category>for</category>
      <category>loop</category>
    </item>
    <item>
      <title>TIL: The smart difference between infinite for loops that work and those that break</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Sun, 21 Mar 2021 18:33:41 +0000</pubDate>
      <link>https://dev.to/mcaci/til-the-smart-difference-between-infinite-for-loops-that-work-and-those-that-break-3llc</link>
      <guid>https://dev.to/mcaci/til-the-smart-difference-between-infinite-for-loops-that-work-and-those-that-break-3llc</guid>
      <description>&lt;p&gt;Consider this Go function with an infinite &lt;strong&gt;for&lt;/strong&gt; loop:&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;func&lt;/span&gt; &lt;span class="n"&gt;exampleA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* do something */&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&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;Take a moment to reflect on this question: Does this code break at compilation time?&lt;/p&gt;

&lt;p&gt;If you think: "well yes, there is a missing return before the function closes; take as example the following code where a break is introduced before the return. How could this function work?"; I would agree that your statement and example is correct and that &lt;code&gt;exampleB&lt;/code&gt; would indeed get a &lt;em&gt;missing return&lt;/em&gt; message from the compiler&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;func&lt;/span&gt; &lt;span class="n"&gt;exampleB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&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;However you may very well be surprised to discover that, if you leave the function &lt;code&gt;exampleA&lt;/code&gt; unaltered, without the missing return at the end, and test it somewhere (for example in &lt;a href="https://play.golang.org%5D"&gt;Go's Playground&lt;/a&gt; it will compile and execute without complaining.&lt;/p&gt;

&lt;p&gt;How is it possible?&lt;/p&gt;

&lt;p&gt;An infinite &lt;code&gt;for&lt;/code&gt; statement without a break inside is considered by the compiler as a &lt;strong&gt;terminating statement&lt;/strong&gt;, a statement that is located at the end of a list of statement and that blocks the execution of any further statements within the same block.&lt;/p&gt;

&lt;p&gt;Which means that the following example also works despite the absence of any return statement.&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;func&lt;/span&gt; &lt;span class="n"&gt;exampleC&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&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;The infinite &lt;code&gt;for&lt;/code&gt; loop with no breaks is not the only terminating statement present in Go; for more details please consult &lt;a href="https://golang.org/ref/spec#Terminating_statements"&gt;this section&lt;/a&gt; of the golang reference spec.&lt;/p&gt;

&lt;p&gt;Hope this was helpful, thanks a lot for your time reading it!&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>go</category>
      <category>tricks</category>
    </item>
    <item>
      <title>TIL: A (maybe) unexpected usage of the -count flag in Go tests</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Fri, 12 Feb 2021 18:32:49 +0000</pubDate>
      <link>https://dev.to/mcaci/til-a-maybe-unexpected-usage-of-the-count-flag-in-go-tests-3dip</link>
      <guid>https://dev.to/mcaci/til-a-maybe-unexpected-usage-of-the-count-flag-in-go-tests-3dip</guid>
      <description>&lt;p&gt;Normally when you add the &lt;code&gt;-count $N&lt;/code&gt; flag to the &lt;code&gt;go test&lt;/code&gt; command the result is that any tests and/or benchmarks that would be run are run &lt;strong&gt;$N&lt;/strong&gt; times as we can see in the following run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt; 1 &lt;span class="nt"&gt;-bench&lt;/span&gt; 1 &lt;span class="nt"&gt;-count&lt;/span&gt; 3
&lt;span class="o"&gt;===&lt;/span&gt; RUN   Test1Sort
&lt;span class="nt"&gt;--------&lt;/span&gt; PASS: Test1Sort &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===&lt;/span&gt; RUN   Test1Sort
&lt;span class="nt"&gt;--------&lt;/span&gt; PASS: Test1Sort &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;===&lt;/span&gt; RUN   Test1Sort
&lt;span class="nt"&gt;--------&lt;/span&gt; PASS: Test1Sort &lt;span class="o"&gt;(&lt;/span&gt;0.00s&lt;span class="o"&gt;)&lt;/span&gt;
goos: linux
goarch: amd64
Benchmark1Sort
Benchmark1Sort-12          10370            113657 ns/op
Benchmark1Sort-12          10488            114596 ns/op
Benchmark1Sort-12           8942            115987 ns/op
PASS
ok      _/home/mcaci/code/github.com/mcaci/dev-art/bench        5.422s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just a side note, the &lt;em&gt;1&lt;/em&gt; put as argument of &lt;code&gt;-run&lt;/code&gt; and &lt;code&gt;-bench&lt;/code&gt; are &lt;strong&gt;regular expressions&lt;/strong&gt; to identify respectively which tests and which benchmarks to run; for more informations on benchmarks, you can read this &lt;a href="https://dev.to/mcaci/introduction-to-benchmarks-in-go-3cii"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Getting back to the situation described in the title, let's look at this situation where we have a test run that is cached after the first time it is run.&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="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt; 1 &lt;span class="nb"&gt;.&lt;/span&gt;
ok      _/home/mcaci/code/github.com/mcaci/dev-art/bench        0.017s
&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt; 1 &lt;span class="nb"&gt;.&lt;/span&gt;
ok      _/home/mcaci/code/github.com/mcaci/dev-art/bench        &lt;span class="o"&gt;(&lt;/span&gt;cached&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt; 1 &lt;span class="nb"&gt;.&lt;/span&gt;
ok      _/home/mcaci/code/github.com/mcaci/dev-art/bench        &lt;span class="o"&gt;(&lt;/span&gt;cached&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tests results are cached when they are run in &lt;em&gt;package list mode&lt;/em&gt; as long as there are no differences in the package code. This is done in order to avoid repeating tests that are already passing and for which no change has been done.&lt;/p&gt;

&lt;p&gt;However, what if we didn't want to use the cache but repeat the tests anyway?&lt;/p&gt;

&lt;p&gt;Here is where the flag &lt;code&gt;-count&lt;/code&gt; comes to our aid.&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="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-timeout&lt;/span&gt; 1s &lt;span class="nt"&gt;-run&lt;/span&gt; ^Test1Sort&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
ok      _/home/mcaci/code/github.com/mcaci/dev-art/bench        0.019s
&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-timeout&lt;/span&gt; 1s &lt;span class="nt"&gt;-run&lt;/span&gt; ^Test1Sort&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
ok      _/home/mcaci/code/github.com/mcaci/dev-art/bench        0.015s
&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-timeout&lt;/span&gt; 1s &lt;span class="nt"&gt;-run&lt;/span&gt; ^Test1Sort&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
ok      _/home/mcaci/code/github.com/mcaci/dev-art/bench        0.014s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As indicated in the documentation that can be found by running &lt;code&gt;go help testflag&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To disable test caching, use any test flag or argument other than the cacheable flags. The &lt;strong&gt;idiomatic way&lt;/strong&gt; to disable test caching explicitly is to use &lt;strong&gt;-count=1&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And so this was the unexpected usage of the &lt;code&gt;-count&lt;/code&gt; flag in &lt;code&gt;go test&lt;/code&gt;, a hidden gem in the go documentation. To read more about this and testing in go in general both &lt;code&gt;go help test&lt;/code&gt; and &lt;code&gt;go help testflag&lt;/code&gt; are great resources to look at.&lt;/p&gt;

&lt;p&gt;Hope this was helpful, thanks a lot for your time reading it!&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>go</category>
      <category>test</category>
      <category>count</category>
    </item>
    <item>
      <title>Introduction to benchmarks in Go</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Tue, 26 Jan 2021 17:13:03 +0000</pubDate>
      <link>https://dev.to/mcaci/introduction-to-benchmarks-in-go-3cii</link>
      <guid>https://dev.to/mcaci/introduction-to-benchmarks-in-go-3cii</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg376olwdswmy3glm2f5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg376olwdswmy3glm2f5n.png" alt="benchmark_gopher"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Benchmarks in Go are in many ways similar to unit tests but have key differencies and serve a different purpose. As they are not as known as unit tests in Go, this article aims to give an introductory look at Go's benchmarks: how to create, how to run them, how to read the results and a few pointers to some advanced topics in creating benchmark tests in Go.&lt;/p&gt;

&lt;p&gt;Benchmarks are functions that test the performance of Go code, they are included the &lt;code&gt;testing&lt;/code&gt; package of the standard Go library and thus available without any dependecies to external libraries.&lt;/p&gt;

&lt;p&gt;When executing a benchmark, you are provided with some information about the execution time and, if requested, the memory footprint of the code under benchmark.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$go&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt; ^&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-bench&lt;/span&gt; ^&lt;span class="o"&gt;(&lt;/span&gt;Benchmark1Sort&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;
goos: linux
goarch: amd64
Benchmark1Sort-12          10000        105705 ns/op        8224 B/op          2 allocs/op
PASS
ok      _/home/mcaci/code/github.com/mcaci/dev-art/go-bench 1.083s


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Creating a benchmark in Go
&lt;/h2&gt;

&lt;p&gt;To create a benchmark, you need to import in your go file the &lt;code&gt;testing&lt;/code&gt; package and create benchmark functions in a similar way that test functions are created.&lt;/p&gt;

&lt;p&gt;For example, when defining unit tests, we write a function in the form of &lt;code&gt;func TestAny(t *testing)&lt;/code&gt; at the beginning, instead, when we define benchmarks we will create a &lt;strong&gt;&lt;code&gt;func BenchmarkAny(b *testing.B)&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A notable difference in Go's benchmarks with respect to unit tests is the &lt;strong&gt;for loop from 0 to &lt;code&gt;b.N&lt;/code&gt;&lt;/strong&gt;. In fact a benchmark is run multiple times in order to make sure that enough data is collected to improve the accuracy of the performance measurement of the code under benchmark.&lt;/p&gt;

&lt;p&gt;The field &lt;code&gt;b.N&lt;/code&gt; is not a fixed value but it is dynamically adapted to make sure that the benchmark function is run for at least 1 second.&lt;/p&gt;

&lt;p&gt;Here to show is a comparison between a benchmark and a test function:&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;func&lt;/span&gt; &lt;span class="n"&gt;Benchmark1Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generateSlice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Test1Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;generateSlice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unexpected slice size: %d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slice&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;h2&gt;
  
  
  Running benchmarks
&lt;/h2&gt;

&lt;p&gt;The starting point for running Go's benchmarks is the &lt;code&gt;go test&lt;/code&gt; command and here we will see what we need to make sure we're not just running the unit tests.&lt;/p&gt;
&lt;h3&gt;
  
  
  Basic usage
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By itself, &lt;code&gt;go test&lt;/code&gt; runs only unit tests, so we need to add the flag &lt;code&gt;-bench&lt;/code&gt; to instruct go test to run also the benchmarks.&lt;/p&gt;

&lt;p&gt;Specifically, this command runs all unit tests and benchmarks in the current package as denoted by the &lt;strong&gt;.&lt;/strong&gt; added as argument for the &lt;code&gt;-bench&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;The "&lt;strong&gt;.&lt;/strong&gt;" value is actually a regular expression which can describe what benchmarks will be executed. For example &lt;code&gt;go test -bench ^Benchmark1Sort$&lt;/code&gt; will run the benchmark named &lt;em&gt;Benchmark1Sort&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Same as when running unit tests, you can add the &lt;code&gt;-v&lt;/code&gt; flag for &lt;em&gt;verbose&lt;/em&gt;, which will show more details on the benchmarks executed as well as any printed output, logs, fmt.Prints and so on, or &lt;em&gt;add a path&lt;/em&gt; (like "./...") to look for benchmarks on a specific package (or all packages and subpackages).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt;
go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; ./...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Running benchmarks only
&lt;/h3&gt;

&lt;p&gt;To filter out all the unit tests from &lt;code&gt;go test&lt;/code&gt;'s execution the &lt;code&gt;-run ^$&lt;/code&gt; flag should be used.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt; ^&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The flag &lt;code&gt;-run&lt;/code&gt; by itself is used to specify which unit tests should be run. Its argument is a regular expression. When we use &lt;code&gt;^$&lt;/code&gt; as argument  we are effectively filtering out all tests, which means only the benchmarks present in the current package will be executed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running multiple times
&lt;/h3&gt;

&lt;p&gt;Simply add the &lt;code&gt;-count&lt;/code&gt; parameter to run your benchmark as many times as the specified count: the outcome of all the executions will be shown in the output.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt; ^Benchmark1Sort&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-run&lt;/span&gt; ^&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-count&lt;/span&gt; 4
goos: linux
goarch: amd64
Benchmark1Sort-12          10207            134834 ns/op
Benchmark1Sort-12           7554            175572 ns/op
Benchmark1Sort-12           7904            148960 ns/op
Benchmark1Sort-12           8568            147594 ns/op
PASS
ok      _/home/mcaci/code/github.com/mcaci/dev-art/go-bench     7.339s


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This flag is useful when sampling the outcomes of multiple runs to make statistical analisys on the benchmark data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading benchmark results
&lt;/h2&gt;

&lt;p&gt;Let's take again the following example and run it with &lt;code&gt;go test -bench&lt;/code&gt; to examine its output.&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;func&lt;/span&gt; &lt;span class="n"&gt;Benchmark1Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generateSlice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&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;h3&gt;
  
  
  With execution time
&lt;/h3&gt;

&lt;p&gt;For the first analysis we run the benchmark with &lt;code&gt;go test -bench ^Benchmark1Sort$ -run ^$&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt; ^Benchmark1Sort&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-run&lt;/span&gt; ^&lt;span class="err"&gt;$&lt;/span&gt;
goos: linux
goarch: amd64
Benchmark1Sort-12           9252            110547 ns/op
PASS
ok      _/home/mcaci/code/github.com/mcaci/dev-art/go-bench     1.053s


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The output shown is present in any benchmark execution and it shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The information about the &lt;strong&gt;enviroment&lt;/strong&gt; where Go is run, which is also obtained by running &lt;code&gt;go env GOOS GOARCH&lt;/code&gt; (case sensitive)

&lt;ul&gt;
&lt;li&gt;In our example they are &lt;strong&gt;goos: linux&lt;/strong&gt; and &lt;strong&gt;goarch: amd64&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;The &lt;strong&gt;benchmark row&lt;/strong&gt; composed of:

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;name of the benchmark run&lt;/strong&gt;, &lt;em&gt;Benchmark1Sort-12&lt;/em&gt;, that is itself composed of the function name, &lt;em&gt;Benchmark1Sort&lt;/em&gt;, followed by the number of CPUs used for the benchmark run, &lt;em&gt;12&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;number of times&lt;/strong&gt; the loop has been executed, &lt;em&gt;9252&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;average runtime&lt;/strong&gt;, expressed in nanoseconds per operation, of the tested function, &lt;code&gt;sort.Ints(generateSlice(1000))&lt;/code&gt;, which is in this case &lt;em&gt;110547 ns/op&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;The information about the benchmark overall status, the package(s) under benchmark and the total time for the execution.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Quick note on the number of CPUs: this parameter can be specified by using the &lt;code&gt;-cpu&lt;/code&gt; flag; the benchmark will be run multiple times once per CPU defined in the flag.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt; ^Benchmark1Sort&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-run&lt;/span&gt; ^&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-cpu&lt;/span&gt; 1,2,4
goos: linux
goarch: amd64
Benchmark1Sort              9280            113086 ns/op
Benchmark1Sort-2            9379            117156 ns/op
Benchmark1Sort-4            8637            118818 ns/op
PASS
ok      _/home/mcaci/code/github.com/mcaci/dev-art/go-bench     3.234s


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If this flag is omitted, a default value is taken from the Go variable &lt;em&gt;GOMAXPROCS&lt;/em&gt; and the number of CPUs is not printed in the output when it's equal to 1.&lt;/p&gt;

&lt;h3&gt;
  
  
  With execution time and memory
&lt;/h3&gt;

&lt;p&gt;To add the information about memory footprint in the output you can add the &lt;code&gt;-benchmem&lt;/code&gt; flag as follows.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt; ^Benchmark1Sort&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-run&lt;/span&gt; ^&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-benchmem&lt;/span&gt;

goos: linux
goarch: amd64
Benchmark1Sort-12          10327            116903 ns/op            8224 B/op          2 allocs/op
PASS
ok      _/home/mcaci/code/github.com/mcaci/dev-art/go-bench     2.128s


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Two new columns have been added in the output of the benchmark row:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;number of bytes&lt;/strong&gt; required by the operation under benchmark, &lt;em&gt;8224 B/op&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;number of allocations&lt;/strong&gt; done by the operation under benchmark, &lt;em&gt;2 allocs/op&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Writing more complex benchmarks
&lt;/h2&gt;

&lt;p&gt;Here are some examples of how to write more complex benchmarks.&lt;/p&gt;

&lt;h3&gt;
  
  
  StartTimer/StopTimer/ResetTimer
&lt;/h3&gt;

&lt;p&gt;When there is the need to do some setup before actually measuring the time spent to execute code to benchmark, the usage of &lt;code&gt;StartTimer&lt;/code&gt;, &lt;code&gt;StopTimer&lt;/code&gt; and &lt;code&gt;ResetTimer&lt;/code&gt; helps to isolate the bits of code that actually need to be taken into account by the benchmark tools.&lt;/p&gt;

&lt;p&gt;Let's take the previous snippet, isolate the creation of the slice from the sorting operation and just measure the execution of the latter.&lt;/p&gt;

&lt;p&gt;To do so we can write:&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;func&lt;/span&gt; &lt;span class="n"&gt;Benchmark2aSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StopTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;generateSlice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;By using &lt;code&gt;b.StopTimer()&lt;/code&gt; we signal that from this point on the execution is not going to be part of the benchmark until &lt;code&gt;b.StartTimer()&lt;/code&gt; is invoked, which means that in each loop, we only consider the data collected during the execution of &lt;code&gt;sort.Ints(s)&lt;/code&gt; for the benchmark.&lt;/p&gt;

&lt;p&gt;If we want to prepare the slice at the beginning and make it an invariant for the benchmark we can write instead:&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;func&lt;/span&gt; &lt;span class="n"&gt;Benchmark2bSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;generateSlice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResetTimer&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;By using &lt;code&gt;b.ResetTimer()&lt;/code&gt; we discard all data collected so far and start anew the collection of data for the benchmark, effectively ignoring the execution time of the &lt;code&gt;generateSlice&lt;/code&gt; call in the overall results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benchmark test cases and subbenchmarks
&lt;/h3&gt;

&lt;p&gt;Like tests, also benchmarks can benefit from the structure of test cases and execution loop to create subbenchmarks.&lt;/p&gt;

&lt;p&gt;Let's see an example:&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;func&lt;/span&gt; &lt;span class="n"&gt;Benchmark3Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;benchData&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&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;size&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="s"&gt;"with size 1000"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s"&gt;"with size 10000"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s"&gt;"with size 100000"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s"&gt;"with size 1000000"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResetTimer&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;benchName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&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;benchData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StopTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;generateSlice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;benchName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;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;In this example we make use of a &lt;code&gt;map[string]struct{...}&lt;/code&gt; to define our benchmark cases and data as we would do for complex tests with test cases and we invoke the &lt;code&gt;b.Run(name string, f func(*testing.B))&lt;/code&gt; to create &lt;em&gt;subbenchmarks&lt;/em&gt; that execute separately our benchmark tests.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt; ^Benchmark3Sort&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nt"&gt;-run&lt;/span&gt; ^&lt;span class="err"&gt;$&lt;/span&gt;
goos: linux
goarch: amd64
Benchmark3Sort/with_size_1000000-12                   10         130396565 ns/op
Benchmark3Sort/with_size_1000-12                   23210             58078 ns/op
Benchmark3Sort/with_size_10000-12                   1300            865703 ns/op
Benchmark3Sort/with_size_100000-12                   118           8718656 ns/op
PASS
ok      _/home/mcaci/code/github.com/mcaci/dev-art/go-bench     6.670s


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice that the name of the benchmark cases are appended to the &lt;em&gt;benchmark name&lt;/em&gt; as part of the output of the benchmark operation as &lt;strong&gt;benchmark_name/benchmark_case_name-number-of-cpus&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting thoughts
&lt;/h2&gt;

&lt;p&gt;There is still a long way to describe how benchmarks work in Go and to get deeper knowledge in how to write them effectively. One of the main topics that would need its own article would be the benchmark of concurrent code in Go with the usage of the &lt;code&gt;b.RunParallel&lt;/code&gt; calls, however I hope this article helps in giving the basics of benchmarks in Go and some grounds to explore the functionalities and tools that have not mentioned here.&lt;/p&gt;

&lt;p&gt;You can find me up on twitter @nikiforos_frees or here on dev.to &lt;a class="mentioned-user" href="https://dev.to/mcaci"&gt;@mcaci&lt;/a&gt; and I'm looking forward to hearing your questions or comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This was Michele, thanks for reading!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://golang.org/pkg/testing/" rel="noopener noreferrer"&gt;Go's testing package&lt;/a&gt; and &lt;a href="https://golang.org/cmd/go/#hdr-Testing_flags" rel="noopener noreferrer"&gt;go cmd testing flags&lt;/a&gt; from the Go team&lt;/li&gt;
&lt;li&gt;Dave Cheney's &lt;a href="https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go" rel="noopener noreferrer"&gt;How to write benchmarks in Go&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/justforfunc/analyzing-the-performance-of-go-functions-with-benchmarks-60b8162e61c6" rel="noopener noreferrer"&gt;Justforfunc&lt;/a&gt;'s article about benchmarks by Francesc Campoy&lt;/li&gt;
&lt;li&gt;Source of benchmark examples inside &lt;a href="https://www.instana.com/blog/practical-golang-benchmarks/" rel="noopener noreferrer"&gt;instana.com's Practical Golang benchmarks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Talk on advanced benchmarks by Daniel Marti given at the DotGo19 conference: &lt;a href="https://www.dotconferences.com/2019/03/daniel-marti-optimizing-go-code-without-a-blindfold" rel="noopener noreferrer"&gt;Optimizing go code without a blindfold&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>benchmark</category>
    </item>
    <item>
      <title>Clearing your Unix Terminal and other commands using Go scripts</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Wed, 20 Jan 2021 19:12:12 +0000</pubDate>
      <link>https://dev.to/mcaci/clearing-your-unix-terminal-and-other-commands-using-go-scripts-37ao</link>
      <guid>https://dev.to/mcaci/clearing-your-unix-terminal-and-other-commands-using-go-scripts-37ao</guid>
      <description>&lt;p&gt;When you want to run shell commands, like for example clearing the terminal, from a Go program or script this is how you can do:&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="n"&gt;cmdName&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"clear"&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmdName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's important to add the &lt;code&gt;cmd.Stdout = os.Stdout&lt;/code&gt; line (you can replace &lt;code&gt;os.Stdout&lt;/code&gt; with any &lt;code&gt;io.Writer&lt;/code&gt; variable) if you want the output of the command to appear somewhere. This is not necessary however if the command does not output anything.&lt;/p&gt;

&lt;p&gt;Launching commands in the terminal is always a useful tool, and very welcome in a Go script. To see it in action, I prepared a fun example of a checkerboard that randomly increases a cell value and prints the equivalent number in &lt;em&gt;Japanese&lt;/em&gt; (from 0 to 3).&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;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"math/rand"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"os/exec"&lt;/span&gt;
    &lt;span class="s"&gt;"strings"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&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;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
    &lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;l&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;cellFlip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;board&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plotted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;400&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&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;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"clear"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&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;cellFlip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;)&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;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;++&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;plotted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Builder&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Grow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;l&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;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cell&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;b&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteRune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toRune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cell&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;i&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteRune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&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;toRune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt; &lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;rune&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="kt"&gt;rune&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;cell&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0x53E3&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0x4E00&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0x4E8C&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0x4E09&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'x'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;0x53E3, 0x4E00, 0x4E8C and 0x4E09 are the codes for 口 (ro which is coming from ゼロ/zero), 一 (ichi) , 二 (ni) and 三 (san) that are the first three numbers in Japanese whose codes are referenced from the Unicode and that can be consulted &lt;a href="https://www.unicode.org/charts/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please also refer to the  `os/exec' &lt;a href="https://golang.org/pkg/os/exec/"&gt;package&lt;/a&gt; to know more about how to launch commands.&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>go</category>
      <category>shell</category>
      <category>cmd</category>
    </item>
    <item>
      <title>How to create an orphan branch in git</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Mon, 18 Jan 2021 17:37:56 +0000</pubDate>
      <link>https://dev.to/mcaci/how-to-create-an-orphan-branch-in-git-35ac</link>
      <guid>https://dev.to/mcaci/how-to-create-an-orphan-branch-in-git-35ac</guid>
      <description>&lt;p&gt;Sometimes you may need to create a brand new branch on a git project that doesn't contain anything present on the other branches nor shares an history with them, called &lt;em&gt;orphan branch&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This snippet describes how to do it:&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="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
git checkout &lt;span class="nt"&gt;--orphan&lt;/span&gt; &lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;
git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; .gitignore
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"# &lt;/span&gt;&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; README.md
git add README.md
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit for branch &lt;/span&gt;&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
git push origin &lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This snippet can be used as a sequence of commands, replacing &lt;code&gt;$1&lt;/code&gt; with any value for the branch name, or in a bash script, for example naming it orphan_branch.sh and running it with &lt;code&gt;sh ./orphan_branch.sh new_branch_name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;More information can be found in the git reference guide at the &lt;a href="https://git-scm.com/docs/git-checkout#Documentation/git-checkout.txt---orphanltnewbranchgt"&gt;git checkout&lt;/a&gt; documentation.&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>git</category>
      <category>checkout</category>
      <category>orphan</category>
    </item>
    <item>
      <title>The meaning of the '.PHONY' target inside a Makefile</title>
      <dc:creator>Michele Caci</dc:creator>
      <pubDate>Fri, 08 Jan 2021 17:13:07 +0000</pubDate>
      <link>https://dev.to/mcaci/the-meaning-of-the-phony-target-inside-a-makefile-4fj8</link>
      <guid>https://dev.to/mcaci/the-meaning-of-the-phony-target-inside-a-makefile-4fj8</guid>
      <description>&lt;p&gt;Inside the &lt;code&gt;Makefile&lt;/code&gt; of a project you can find a &lt;code&gt;.PHONY&lt;/code&gt; element followed by a label and then the same label used as a &lt;a href="https://www.gnu.org/software/make/manual/html_node/Rules.html#index-target"&gt;target&lt;/a&gt; for the Makefile.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;
&lt;span class="nl"&gt;build&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        go build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.PHONY&lt;/code&gt; is actually itself a target for the &lt;code&gt;make&lt;/code&gt; commandand and it denotes labels that do not represent files of the project. What does it mean?&lt;/p&gt;

&lt;p&gt;In the general case, assuming that there are no files called &lt;strong&gt;build&lt;/strong&gt; in the project, when not using the &lt;code&gt;.PHONY&lt;/code&gt; target, like so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;build&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        go build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;everytime the &lt;code&gt;make build&lt;/code&gt; command is invoked it will execute the specified command (in this case &lt;code&gt;go build&lt;/code&gt;). However, if there was a file named &lt;strong&gt;build&lt;/strong&gt;, the &lt;code&gt;make build&lt;/code&gt; would be bound by the presence of this file and executed only if that file was updated.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.PHONY&lt;/code&gt; target overrides this last behaviour and let's the &lt;code&gt;make build&lt;/code&gt; execute no matter of the presence of a file named &lt;strong&gt;build&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For a more in-depth overview head to the &lt;code&gt;make&lt;/code&gt; command &lt;a href="https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html"&gt;reference&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>makefile</category>
      <category>make</category>
    </item>
  </channel>
</rss>
