<?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: Adelina Simion 🥑</title>
    <description>The latest articles on DEV Community by Adelina Simion 🥑 (@addetz).</description>
    <link>https://dev.to/addetz</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%2F809932%2F4ece7048-5c89-42df-a757-b8c2d1a06598.jpeg</url>
      <title>DEV Community: Adelina Simion 🥑</title>
      <link>https://dev.to/addetz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/addetz"/>
    <language>en</language>
    <item>
      <title>Craft Yourself a Sustainable Tech Career</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Sat, 09 Mar 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/craft-yourself-a-sustainable-tech-career-1eil</link>
      <guid>https://dev.to/addetz/craft-yourself-a-sustainable-tech-career-1eil</guid>
      <description>&lt;p&gt;This year marks my tenth anniversary of working in tech. I graduated from university in Denmark at the end of 2013. I moved to London in the spring of 2014 and took a graduate Java developer position. Except for the odd 1-2 month break between jobs, I have been working full time for the past decade.&lt;/p&gt;

&lt;p&gt;I take immense pride in my career and my achievements, but the road has not been easy. Sometimes others wanted me to fail, sometimes I doubted myself, and sometimes I dreamt about packing it all in. But here I am, a decade later… still standing! 💪&lt;/p&gt;

&lt;p&gt;When it comes to your career, the race is an ultra-marathon through the desert in cheap shoes, not a nice jog on a manicured lawn. Keeping a sustainable pace is the key to success.&lt;/p&gt;

&lt;p&gt;This post is a collection of lessons that I learned the hard way, which helped me stay consistent and show up another day. I hope they will also help you.&lt;/p&gt;

&lt;p&gt;💐 &lt;strong&gt;Happy International Women’s Day!&lt;/strong&gt; 💐&lt;/p&gt;

&lt;h2&gt;
  
  
  You don’t have to be beyond reproach.
&lt;/h2&gt;

&lt;p&gt;When I first started as an engineer, I felt like I could not make any mistakes and my work should be the best I could possibly deliver. &lt;em&gt;“Push yourself, work harder than everyone else, show them that you mean business!”&lt;/em&gt; became the mantra that I would repeat to myself every day. Of course, this affected my mental health, pushed me to drink alcohol to cope with anxiety and stopped me from learning. Within the first two years, I was miserable and questioning my career choice.&lt;/p&gt;

&lt;p&gt;True equality in tech does not mean that the minorities need to be better than everyone else, but still get paid the same. You are allowed the same grace and understanding as your peers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are allowed to make the same mistakes.&lt;/li&gt;
&lt;li&gt;You are allowed learn at the same pace.&lt;/li&gt;
&lt;li&gt;You should be given as many chances and opportunities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your place in tech is just as valid as everyone else’s. You don’t need to outperform to be worthy. Give yourself the space to make mistakes and learn from them, so that you can grow and have a sustainable tech career.&lt;/p&gt;

&lt;h2&gt;
  
  
  Never make yourself small.
&lt;/h2&gt;

&lt;p&gt;I worked in-office jobs up until the pandemic in 2020. Six years of 2hr travel time each day. Six LONG years of showing up to the office every day and having to sit through in-person meetings. When I attended meetings, I would sit in the back, pull my shoulders forward, and hope that nobody talks to me. Typically, I didn’t speak in these meetings. On the rare occassions that I did, I would state my opinions as questions, hesitantly and unconfidently. I made myself &lt;em&gt;small&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When you feel like you don’t belong, you don’t want to be noticed or singled out. However, people who don’t get noticed also don’t get given interesting opportunities, don’t get promoted and they definitely don’t get raises. &lt;em&gt;Trust me, I know.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It can be helpful to imagine you are playing a part, a &lt;em&gt;work persona&lt;/em&gt;. You can imagine who this person is, the kind of questions they ask and how they are perceived by others. Then, use your imagination to apply your mannerisms to your work persona. You are playing the part of a lifetime, so you’ve got to sell it! As you reconcile image of yourself and your work personna, you begin to show up to work in a confident way. The work personna is a crutch you won’t need forever, but it will allow you to let go of your perceived limitations.&lt;/p&gt;

&lt;p&gt;As I mentioned in the previous section, you should never question your place in tech. You should be free to ask questions and voice your opinions when you go to meetings as well. Your thoughts are worth just as much as everyone else’s, so don’t hold them back. Getting noticed, demonstrating leadership and confidence, will craft you a sustainable tech career by setting you up for success when the next performance review comes around. 🤞&lt;/p&gt;

&lt;h2&gt;
  
  
  You are not an impostor.
&lt;/h2&gt;

&lt;p&gt;At the beginning of my career, I was fully convinced that I was the person in the room that knew the least. That was fine because I was going to work extra hard and get better. Being a newly minted junior engineer is extremely liberating. Your job is quite simple: soak up knowledge, deliver work as instructed, and keep improving. This freedom doesn’t last, so make sure you enjoy every minute of it. As you get experience and credibility, the expectations of those around you increase. It was around the four-year experience mark that I first experienced the dreaded &lt;em&gt;impostor syndrome&lt;/em&gt;, even though I did not know how to verbalise it.&lt;/p&gt;

&lt;p&gt;Impostor syndrome warps all of your experiences, as if through a skewed magnifying glass. All of your achievements are minimised, all of your little failures are catastrophised and everyone around you appears to be effortlessly better than you. As these warped thoughts constantly swirl around in your head, the impostor syndrome is reinforced and the magnifying glass gets stronger.&lt;/p&gt;

&lt;p&gt;At my lowest point, I thought I was sure to be let go on the basis of performance. I walked into my performance review expecting the worst. I was absolutely ecstatic when I got a &lt;em&gt;meets expectations&lt;/em&gt;! It was then that I realised how warped my thinking had become.&lt;/p&gt;

&lt;p&gt;The best weapon you have against impostor syndrome is &lt;em&gt;reality&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start to write down every thing you do well and everything you learn, no matter how small.&lt;/li&gt;
&lt;li&gt;Document your wins even when it feels like you have nothing to celebrate.&lt;/li&gt;
&lt;li&gt;As the practice of celebrating your small wins becomes habit, you will see your improvements and begin to advocate for yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my experience, this process will help dismantle the impostor syndrome that has taken hold of your thinking patterns. You will begin to believe your own track record and improve your self confidence.&lt;/p&gt;

&lt;p&gt;Impostor syndrome can cause a lot of people, especially minorities, to feel alienated and eventually leave tech. You can overcome it! Check out &lt;a href="https://www.calm.com/blog/how-to-overcome-imposter-syndrome"&gt;this page from the Calm blog&lt;/a&gt; for more techniques.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lift yourself by lifting others.
&lt;/h2&gt;

&lt;p&gt;As I look back at my career, I don’t remember code, tickets or problems. I remember the people I met along the way and the impact we had on each others’ lives. I think that’s really lovely. 🫶&lt;/p&gt;

&lt;p&gt;Make it your priority to support others, in little or big ways. Show up for others, be compassionate and build a support network around yourself. Even in a larger city like London, I have found that tech is a quite small community. It’s quite handy to have friends in important rooms. 💪&lt;/p&gt;

&lt;p&gt;If you’re not sure where to start, get involved with your local tech communities on meetup or engage online. I’m a firm believer in fostering in-person relationships though, so do try to cultivate a professional network in your area, not rely solely on online connections.&lt;/p&gt;

&lt;p&gt;Working in tech can be lonely and difficult due to the complex nature of the work. Fostering connections with others will make you feel like you belong, as well as provide support to those around you. A sustainable tech career isn’t nurtured in isolation and you are not an island. 🏝️ Personal relationships are sometimes even more important than your technical skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting Thoughts
&lt;/h2&gt;

&lt;p&gt;I can’t believe it’s already been TEN YEARS since I started my career. The last thought I’d like to leave you with is that &lt;em&gt;if I can do it, so can you&lt;/em&gt;. It doesn’t matter whether you are trying to get your first job in tech or are looking for a new opportunity following a redundancy, you will find your next opportunity.&lt;/p&gt;

&lt;p&gt;We can do hard things and will overcome whatever this ultra-marathon in the desert throws at us. 🏜️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExcXA1N2hoeGJnNTAyN3gwamhpcG5vaGFvNWJsb3c1MjByZWc5dnJqaSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/Q21Nnq7Qjem0QsC4Fp/giphy.gif"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExcXA1N2hoeGJnNTAyN3gwamhpcG5vaGFvNWJsb3c1MjByZWc5dnJqaSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/Q21Nnq7Qjem0QsC4Fp/giphy.gif" alt="We can do hard things!" width="400" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>wecoded</category>
      <category>womenintech</category>
    </item>
    <item>
      <title>All Gophers aboard! Deploying your first Go app to Railway 🛤️</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Wed, 23 Aug 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/all-gophers-aboard-deploying-your-first-go-app-to-railway-l78</link>
      <guid>https://dev.to/addetz/all-gophers-aboard-deploying-your-first-go-app-to-railway-l78</guid>
      <description>&lt;p&gt;Railway is a modern PaaS solution that makes deploying code easier. I’ve had a bit of time to experiment with it and was keen to write up my findings for how it worked with Go projects. In this post, I explore the magic of its deployment mechanisms and demonstrate how to use GitHub Actions to deploy code to Railway. &lt;strong&gt;Spoiler alert&lt;/strong&gt;: I loved learning about Railway and will be building with it more in the future!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.giphy.com/media/9PxpzVxz4aNTbz0DaR/giphy.gif"&gt;&lt;img src="https://i.giphy.com/media/9PxpzVxz4aNTbz0DaR/giphy.gif" alt="Love it!" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Railway? 🛤️
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://railway.app/"&gt;Railway&lt;/a&gt; is often &lt;a href="https://docs.railway.app/reference/compare-to-heroku"&gt;compared to Heroku&lt;/a&gt; because it makes the provisioning of infrastructure and deployment of code much easier than other public cloud providers. This is perfect for me, a backend engineer who wants to build stuff!&lt;/p&gt;

&lt;p&gt;Here are some of the key headline features of the platform:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero configuration builds&lt;/strong&gt; : the Railway team have started the &lt;a href="https://github.com/railwayapp/nixpacks"&gt;Nixpacks&lt;/a&gt; project. This project builds OCI compliant images based on the source repository. They currently support a variety of &lt;a href="https://docs.railway.app/deploy/builds"&gt;popular languages&lt;/a&gt; out of the box, including Go ⭐️ of course! For other languages, you can supply your own Docker file and still run on Railway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-built GitHub support&lt;/strong&gt; : Railway services can be tied to a GitHub repository. Then, changes committed to configured branches automatically trigger services to be re-deployed. The cherry on top 🍒 is that the Railway CLI also makes it easy to configure GitHub Actions workflows. I will show you how this works later on in this post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets management&lt;/strong&gt; : once deployed, Railway services are organised into environments, which then belong to projects. You can easily configure project secrets which are &lt;em&gt;shared&lt;/em&gt; between different services in the same project. Services can also have their own defined secrets. This approach to secrets management gives you a lot of configuration flexibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Templates&lt;/strong&gt; : the Railway team and community have created templates for even easier code deployment. You can create a project from a template, which then creates a public GitHub repo using your GitHub user. This repository is then linked to a Railway service using the previously mentioned GitHub support. At the time of writing, there are templates for the most popular Go web frameworks: &lt;a href="https://gofiber.io/"&gt;fiber&lt;/a&gt;, &lt;a href="https://gin-gonic.com/"&gt;gin&lt;/a&gt;, &lt;a href="https://pkg.go.dev/github.com/gorilla/mux"&gt;gorilla/mux&lt;/a&gt; and &lt;a href="https://go-chi.io/#/"&gt;chi&lt;/a&gt;. The big advantage of using a template is that you will also receive updates when the template itself is updated. Railway also runs an &lt;a href="https://railway.app/open-source-kickback"&gt;OSS kickback programme&lt;/a&gt; which gives back 25% of template usage revenue to the template creators. That’s a great incentive for the Go community to extend Railway support! 🤑&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that I have covered the fundamentals of Railway, let’s get hands on and see how easy it &lt;em&gt;really&lt;/em&gt; is to run on Railway! 🚆&lt;/p&gt;

&lt;p&gt;&lt;a href="https://railway.app/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1rn2m8hl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-banner.png" alt="Railway banner" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Signing up &amp;amp; setting up 🛠️
&lt;/h2&gt;

&lt;p&gt;As you might imagine, signing up and onboarding are pretty painless. When creating an account, you can choose to sign up via email or using your GitHub account. I would recommend using your GitHub account, as that will also add Railway as a &lt;a href="https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps"&gt;GitHub app&lt;/a&gt;, which will make it easier for you to leverage GitHub integrations later on. Once signed up, you will be put on the Trial plan which will give you a free $5 allowance to explore Railway with. &lt;a href="https://railway.app/pricing"&gt;Pricing&lt;/a&gt; then starts from $5 a month with the Hobby plan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://railway.app/pricing"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i7H8zowe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-pricing.png" alt="Railway pricing" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you’re all set up, you can create a new project from your &lt;a href="https://railway.app/dashboard"&gt;dashboard&lt;/a&gt; or through the &lt;a href="https://docs.railway.app/develop/cli"&gt;Railway CLI&lt;/a&gt;. Since I’ve never been a fan of ClickOps, I’ll do as much as possible using the CLI, even though the dashboard is easy to use and inspect. The CLI can be installed in a &lt;a href="https://docs.railway.app/develop/cli#installation/"&gt;variety of ways&lt;/a&gt; depending on your OS. I installed it using &lt;a href="https://brew.sh/"&gt;homebrew&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;railway

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

&lt;/div&gt;



&lt;p&gt;Once installed, you will need to authenticate your CLI session in your terminal:&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;railway login

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

&lt;/div&gt;



&lt;p&gt;This command will authenticate you by launching a new browser window, but there is also a &lt;code&gt;-browserless&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;As previously mentioned, Railway organises your work in projects. I must now create a new project which can be the home of my upcoming deployments:&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;railway init
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Project Name Will be randomly generated
Created project sneaky-window on Personal
https://railway.app/project/ee5d0509-b356-4581-a5af-d4dfcce84001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can provide a name for your project or have a random one generated as above. A URL to inspect your project on the dashboard is also printed out. &lt;em&gt;By the time this blogpost publishes, this project will have already been torn down, but it might be a good idea to keep this key secret!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By default, all projects have a generated &lt;code&gt;production&lt;/code&gt; environment. All Railway &lt;a href="https://docs.railway.app/develop/environments"&gt;environments&lt;/a&gt; contain the same services, but give you isolated instances that you can experiment on separately. You can create new environments using the Railway dashboard, but can then change between them from the CLI. A really neat feature is that environments can be &lt;a href="https://docs.railway.app/develop/environments#forking-and-merging-environments"&gt;forked and merged&lt;/a&gt; as well. Going forward, I'll only be working in the default &lt;code&gt;production&lt;/code&gt; environment.&lt;/p&gt;

&lt;p&gt;That’s all the setup you need for now: you’ve signed up to Railway, set up your CLI for easier management and created a new project that you can deploy your work to. It’s time to get some Go code ready for deployment! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  The Go European Weather checker 🇪🇺
&lt;/h2&gt;

&lt;p&gt;I’ve written a small Go app that displays the weather in the European capitals as part of this Railway experiment. You can see it on GitHub at &lt;a href="https://github.com/addetz/go-weather-checker"&gt;addetz/go-weather-checker&lt;/a&gt;. I have written this app from scratch, but I could have used one of the Railway Go templates as the starting point.&lt;/p&gt;

&lt;p&gt;This little application uses the following technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/labstack/echo"&gt;labstack/echo&lt;/a&gt; is my chosen web framework. I’ve recently started using this framework and I really like how easy it is to configure routes, as well as construct JSON responses.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/gopherjs/gopherjs"&gt;GopherJS&lt;/a&gt; compiles Go code to JavaScript. I built a very small frontend to make the demo more visually appealing. This library allowed me to build the entire demo in Go, except for some simple HTML. The frontend is styled with &lt;a href="https://getbootstrap.com/"&gt;bootstrap&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://openweathermap.org/"&gt;OpenWeatherMap&lt;/a&gt; is the third-party service that I use to fetch weather data. This service provides you with 1000 free API calls per day. As part of sign up, you will be issued with an API key that you can use for querying.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application is configured with 2 environment variables: the OpenWeatherMap API key mentioned above is mandatory and the port is optional, with a default value of &lt;code&gt;8080&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;WEATHER_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;XXX
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;XXX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After setting our variables, the server runs like any old server:&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 run server.go

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

&lt;/div&gt;



&lt;p&gt;Once the server starts up, you can navigate to it in the browser at &lt;code&gt;localhost:8080&lt;/code&gt; or whatever port you have configured. Now you can see what the weather is in any European capital! 😎&lt;/p&gt;




&lt;h2&gt;
  
  
  Deploying to Railway 🚆
&lt;/h2&gt;

&lt;p&gt;As mentioned above, the source for my app is at &lt;a href="https://github.com/addetz/go-weather-checker"&gt;addetz/go-weather-checker&lt;/a&gt;. The repo does not have a Dockerfile, but it does contain a &lt;code&gt;go.mod&lt;/code&gt; file which will signal to Nixpacks that this is a Go application.&lt;/p&gt;

&lt;p&gt;Back in my terminal, I link the repo root directory of the weather app with the previously created &lt;code&gt;sneaky-window&lt;/code&gt; project and its default created &lt;code&gt;production&lt;/code&gt; environment:&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;railway &lt;span class="nb"&gt;link&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Select a project sneaky-window
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Select an environment production

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

&lt;/div&gt;



&lt;p&gt;Linking my CLI session to this project allows me to run all future commands against this project and environment. I can then easily deploy the weather app using the &lt;code&gt;up&lt;/code&gt; command:&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;railway up

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

&lt;/div&gt;



&lt;p&gt;At this point, Nixpacks will build and publish an image for my app and Railway will attempt to start a service running  its built image. However, this service will immediately crash because I have not set up any secrets for my application. The deploy logs simply print the following and the application exits. 😱&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2023/08/24 14:22:33 WEATHER_API_KEY must be set

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

&lt;/div&gt;



&lt;p&gt;At the time of writing, the Railway team are &lt;a href="https://docs.railway.app/develop/cli#cli-v3-changes"&gt;rethinking the secrets workflow within the CLI&lt;/a&gt;, so I am not be able to add the mandatory secret from the terminal. Instead, I add it as a &lt;a href="https://docs.railway.app/develop/variables#shared-variables"&gt;shared variable&lt;/a&gt; to the project by navigating to the &lt;a href="https://railway.app/dashboard"&gt;Railway dashboard&lt;/a&gt; and adding it to the project settings, then sharing it with the newly created weather service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T50KLzNJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-shared-variables.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T50KLzNJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-shared-variables.png" alt="Railway shared variables" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this variable is shared, the service will be successfully redeployed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g2I-n1dG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-success-deploy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g2I-n1dG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-success-deploy.png" alt="Railway success deploy" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The running deployment shows us two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Railway is able to detect that I am attempting to expose a webserver.&lt;/li&gt;
&lt;li&gt;The app is now listening on port &lt;code&gt;:5784&lt;/code&gt;, even though this has not been configured at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How on earth is this all happening?&lt;/strong&gt; 🧐&lt;/p&gt;

&lt;p&gt;The secret lies in the magic 🪄 of Railway, of course… and the &lt;code&gt;PORT&lt;/code&gt; environment variable. In order to &lt;a href="https://docs.railway.app/deploy/exposing-your-app"&gt;expose web apps&lt;/a&gt;, Railway needs an IP and port. The IP is provided through configured domains, while the port is configured through a Railway provided &lt;code&gt;PORT&lt;/code&gt; environment variable. If any apps you write are configured to use this variable, they will be able to expose endpoints to the internet without any further configuration.&lt;/p&gt;

&lt;p&gt;There are 2 options for domain configuration: generate one or add a custom domain from the service settings. In this instance, I have generated a domain and my app will be exposed at &lt;code&gt;https://sneaky-window-production.up.railway.app/&lt;/code&gt;. One really neat thing to notice is that Railway has also secured all traffic to my application with HTTPS without me having to configure anything in my app or create certificates. Nixpacks took care of that. 🤩&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A0IlDHd3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-expose.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A0IlDHd3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-expose.png" alt="Railway success deploy" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The cherry on top 🍒: GitHub Actions
&lt;/h2&gt;

&lt;p&gt;As a final step, let’s talk about CI/CD with &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt;. Workflow configuration and management have now become synonymous with GitHub Actions, so of course it makes sense that Railway supports this!&lt;/p&gt;

&lt;p&gt;Railway allows the creation of project tokens in order to authenticate from remotes where even browserless login is not possible. You can create a new token from the &lt;em&gt;Tokens&lt;/em&gt; tab of your project settings. This token will give you programmatic access to the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OJZ_wag2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-token.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OJZ_wag2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-token.png" alt="Railway expose web server" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the GitHub side, I add this token as a secret to the weather app repository &lt;a href="https://github.com/addetz/go-weather-checker"&gt;addetz/go-weather-checker&lt;/a&gt; by navigating to &lt;em&gt;Settings&lt;/em&gt; -&amp;gt; &lt;em&gt;Secrets and Variables&lt;/em&gt; -&amp;gt; &lt;em&gt;Actions&lt;/em&gt;. I will name this token &lt;code&gt;RAILWAY_TOKEN&lt;/code&gt; as advised. I have also added a further secret called &lt;code&gt;RAILWAY_SERVICE&lt;/code&gt;, which will allow me to instruct which service to deploy this repository to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BcRYcoE9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-gha-secret.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BcRYcoE9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-gha-secret.png" alt="Railway GHA token" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You are now ready to run GitHub Actions with Railway! A simple workflow which builds our app, runs our tests and then deploys the code using Railway can be seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Railway&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Go&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1.21.x'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go get ./...&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go build -v ./...&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test with the Go CLI&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go test ./... -v&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Railway&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bervProject/railway-deploy@main&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;railway_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.RAILWAY_TOKEN }}&lt;/span&gt; 
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.RAILWAY_SERVICE }}&lt;/span&gt; 

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

&lt;/div&gt;



&lt;p&gt;I deploy to Railway using an existing &lt;a href="https://github.com/bervProject/railway-deploy"&gt;railway-deploy GitHub Action&lt;/a&gt;, which wraps around the installation aspects of the CLI. I make use of the configured repository variables to pass the token and the deployment service.&lt;/p&gt;

&lt;p&gt;That’s all you need to seamlessly deploy your application to Railway with GitHub Actions. One aspect I have not covered is the ability to specify a GitHub repository as the service source, which will allow Railway to monitor the repository for changes on a configured branch, typically &lt;code&gt;main&lt;/code&gt;, and then redeploy when new commits are made. You can read more about service sources and triggers on the &lt;a href="https://docs.railway.app/develop/services#service-source"&gt;Railway docs&lt;/a&gt;. I prefer to have control of deployments using GitHub Actions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bte_W32a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-executed-actions.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bte_W32a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/railway/railway-executed-actions.png" alt="Railway executed actions" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;This brings me to the end of my exploration with Railway! It’s been so interesting to learn about this great platform. There is a lot here that can make our lives easier and help us ship projects faster, so I hope this post will inspire you to explore Railway on your own as well.&lt;/p&gt;

&lt;p&gt;I’ll be following up with a post on how databases &amp;amp; storage work in Railway, so stay tuned for that. And who knows… I might put forward an &lt;code&gt;echo&lt;/code&gt; Railway template as well! 🤩&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy coding, Gophers!❤️&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>railway</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Test-Driven Development in Go: principles and key concepts</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Sat, 06 May 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/test-driven-development-in-go-principles-and-key-concepts-4ma1</link>
      <guid>https://dev.to/addetz/test-driven-development-in-go-principles-and-key-concepts-4ma1</guid>
      <description>&lt;p&gt;&lt;em&gt;Estimated reading time: 6 mins&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I recently had the pleasure of discussing and demonstrating some of the key concepts of my &lt;a href="https://bit.ly/3UFpweU"&gt;“Test-Driven Development in Go”&lt;/a&gt; book on &lt;a href="https://bit.ly/3HG9oVh"&gt;a live stream&lt;/a&gt;. This post summarises the main points covered by this 1hr coding session. Understanding these testing essentials will go a long way to helping you become a TDD practitioner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read on to see why you should care about testing and TDD!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/46ZjWWtY6Qo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Key principles
&lt;/h2&gt;

&lt;p&gt;I was keen to explore the topic of TDD in Go because it was one of the parts of the language that I had a hard time understanding, despite its simplicity. There were only a few functions available in Go’s &lt;code&gt;testing&lt;/code&gt; package, but I was unsure how to use them and it seemed difficult to build any test setup. Figuring out the testing process in Go took some time, especially as most tutorials are aimed at learning language basics, not test basics. I was keen to dedicate time share my knowledge, discover new concepts myself and write a thorough guide to writing testable code with &lt;code&gt;TDD&lt;/code&gt; as the working process. This is why I took on the project of writing a book dedicated to testing techniques and the application of TDD.&lt;/p&gt;

&lt;p&gt;The book is structured around the following four basic principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Writing testable code starts with a thorough understanding of the language you are writing in&lt;/strong&gt; : we need to understand the main structure and concepts of Go in order to be able to write testable code. We need to have a clear understating of concepts such as package structure, dependency injection, concurrency and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TDD is hard because it is difficult to have a clear vision of what we are trying to achieve when problems are ambiguous&lt;/strong&gt; : writing tests is easy in Go, as we use the same techniques as writing source code. Instead, the unclear understanding of the work we are trying to achieve and an over fixation on technical solutions is what makes it difficult to practice TDD.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engineers should take ownership of testing their product at all levels, not just unit&lt;/strong&gt; : testing blogs &amp;amp; demos often focus on unit testing only. While this makes it easy for developers to write tests with small scope, engineers should take ownership of testing at all levels. This has the benefit of giving us a thorough understanding of how users will be ultimately interacting with our product, but also give us ownership of our product in a true DevOps way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practicing TDD can help you organise your work and stay focused on solutions to user-problems&lt;/strong&gt; : the TDD process involves writing tests alongside the source code. This encourages us to make conscious decisions for code structure that is focused on requirements and inputs, as opposed to get overly attached to technical solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tests are typically organised in the &lt;strong&gt;testing pyramid&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;At the bottom of the pyramid, we have &lt;strong&gt;unit tests&lt;/strong&gt; , which only test a single, isolated behaviour or piece of functionality. They are the fastest and most numerous.&lt;/li&gt;
&lt;li&gt;In the middle, we have &lt;strong&gt;integration tests&lt;/strong&gt; , which test the behaviour of multiple components together. They are complementary to unit tests, as they ensure that multiple units work well together not just individually.&lt;/li&gt;
&lt;li&gt;At the top of the pyramid, we have &lt;strong&gt;end-to-end tests&lt;/strong&gt; , which test the entire application. They are typically focused on validating the application exposes the correct user-facing functionality.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--23uHgy6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/tdd/testing_pyramid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--23uHgy6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/tdd/testing_pyramid.png" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;Figure 1 - The core principles of the book.
  &lt;/p&gt;

&lt;h2&gt;
  
  
  The method
&lt;/h2&gt;

&lt;p&gt;The Red-Green-Refactor method is the working process for TDD. It the three steps described in the figure below. In the beginning, it might be cumbersome to swap between source code and test code, but it will quickly become second nature. The three steps of the method are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Red phase&lt;/strong&gt; : based on provided requirements, we begin by writing a test with specified inputs and expected outputs. We run this test to ensure it is failing. This helps us avoid any false positives later on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Green phase&lt;/strong&gt; : swapping over to source code, we write enough code to satisfy the previously written test and implement the functionality required. We re-run this test to ensure that it is now passing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Refactor phase&lt;/strong&gt; : while the test and implementation are successfully fulfilling the requirement we have been focusing on, we can take the time to make any improvements to it in the refactor phase.&lt;/li&gt;
&lt;li&gt;The process repeats until we have successfully implemented all functionality that the unit requires.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tests should &lt;strong&gt;focus on testing outputs, not implementation&lt;/strong&gt;. If tests are tightly coupled implementation concerns,they can become brittle when code is changed or refactored. Tests should be made as resilient to change as possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PGO-wJsq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/tdd/red_green_refactor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PGO-wJsq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/tdd/red_green_refactor.png" width="800" height="452"&gt;&lt;/a&gt;&lt;br&gt;Figure 2 - The Red-Green-Refactor TDD method.
  &lt;/p&gt;

&lt;h2&gt;
  
  
  Unit testing essentials
&lt;/h2&gt;

&lt;p&gt;Now that the process and main mechanisms are established, we can start to look at how to implement our first test. We begin at the bottom of the testing pyramid with unit tests.&lt;/p&gt;

&lt;p&gt;Go functions, structs, variables and interfaces are organised in Go packages. Their visibility is restricted to the package unless exported with a capital letter. Directories can generally only contain a single package with some exceptions. One of these exceptions are &lt;strong&gt;testing packages&lt;/strong&gt;. These packages end with the &lt;code&gt;_test&lt;/code&gt; suffix and must match the name of the source package that is also defined in the same directory. These packages behave like any other external package, only having access to the exported names of the source package.&lt;/p&gt;

&lt;p&gt;This is a very powerful mechanism. The usage of a test package ensures that we only test the externally visible functionality of the package, making our tests the first consumers of the package we are creating. We can then clearly identify what parts of exposed functionality need to be rewritten or clarified.&lt;/p&gt;

&lt;p&gt;In Go, tests are just regular functions which comply to some restrictions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func TestName(t *testing.T) {
  // implementation
}

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Test names start with the &lt;code&gt;Test&lt;/code&gt; prefix followed by the test name in camel case.&lt;/li&gt;
&lt;li&gt;Test functions take a single parameter of type &lt;code&gt;*testing.T&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Tests live in &lt;code&gt;_test.go&lt;/code&gt; files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;testing&lt;/code&gt; package exposes methods logging and failing tests. The &lt;code&gt;t.Error&lt;/code&gt; method fails a test but continues running the test suite, while the &lt;code&gt;t.Fatal&lt;/code&gt; method fails the test and stops the execution of the entire test suite. The &lt;code&gt;t.Errorf&lt;/code&gt; and &lt;code&gt;t.Fatalf&lt;/code&gt; method counterparts which allow us to pass messages for formatting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Wohbefg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/tdd/unit_testing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Wohbefg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/tdd/unit_testing.png" width="800" height="452"&gt;&lt;/a&gt;&lt;br&gt;Figure 3 - Getting started with Go unit tests.
  &lt;/p&gt;

&lt;p&gt;I demonstrate the &lt;strong&gt;Red-Green-Refactor&lt;/strong&gt; method with a simple example and unit tests in the &lt;a href="https://www.youtube.com/live/46ZjWWtY6Qo?feature=share&amp;amp;t=550"&gt;live stream from timestamp 09:10&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration testing
&lt;/h2&gt;

&lt;p&gt;Unit tests do not have sufficient scope to ensure that functional requirements are successfully delivered. Often times, their implementation requires the usage of multiple units or &lt;strong&gt;components&lt;/strong&gt; working together, delivering their specialised functionality in order to build the solution. In these cases, integration tests are often times a useful way to extend scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integration tests cover one or multiple components, ensuring that the individual components work well as a combined entity. In the microservices world, the different components might even be delivered by different teams. The integrations between these separate units are often the cause of errors or outages.&lt;/li&gt;
&lt;li&gt;While the logic of the particular component is verified by its unit tests, the purpose of the integration test is to exercise the conditions at the seams between the components.&lt;/li&gt;
&lt;li&gt;Integration tests have the advantage of allowing us to test bigger scope, without the complexity of having to run an entire application. As they are in the middle of the pyramid, they don’t require the entire application to be ready for running and testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mZlVgGYN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/tdd/integration_testing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mZlVgGYN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/tdd/integration_testing.png" width="800" height="453"&gt;&lt;/a&gt;&lt;br&gt;Figure 4 - Integration tests allow us to test how well components work together.
  &lt;/p&gt;

&lt;p&gt;The code required for implementing integration tests isn’t any different from unit tests. I demonstrate writing integration tests using &lt;code&gt;httptest&lt;/code&gt; in the &lt;a href="https://www.youtube.com/live/46ZjWWtY6Qo?feature=share&amp;amp;t=2678"&gt;live stream from timestamp 44:38&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  End-to-end testing
&lt;/h2&gt;

&lt;p&gt;This stream did not cover end-to-end testing. I may dedicate a future blogpost to this topic, but in the meantime, I recommend that you explore &lt;a href="https://github.com/cucumber/godog"&gt;BDD testing with &lt;code&gt;godog&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/pact-foundation/pact-go"&gt;contract testing with &lt;code&gt;pact&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Let me just get this working and then I’ll see how to test it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Often times, we feel like testing code is of lower importance than source/implementation code. This way of thinking results in complex, unmaintainable code that is riddled with bugs. Spending time unpicking complex code structure for later testing takes longer than incrementally making decisions, ensuring they are easy to test and implementing solutions to provided requirements.&lt;/p&gt;

&lt;p&gt;Therefore, I encourage everyone to take the time to improve and hone their testing practices. You won’t be disappointed with the results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy coding, Gophers!❤️&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;Here are the links mentioned in the stream:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My &lt;a href="https://bit.ly/3UFpweU"&gt;“Test-Driven Development in Go” book&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://bit.ly/3p2ZbeX"&gt;slides presented in this session&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/addetz/gophertale"&gt;repository with the demo code&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>tdd</category>
      <category>code</category>
    </item>
    <item>
      <title>The Future of Code Week: Will Languages like Go and Rust Overtake their Legacy?</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Mon, 14 Nov 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/the-future-of-code-week-will-languages-like-go-and-rust-overtake-their-legacy-2omi</link>
      <guid>https://dev.to/addetz/the-future-of-code-week-will-languages-like-go-and-rust-overtake-their-legacy-2omi</guid>
      <description>&lt;p&gt;&lt;em&gt;Estimated reading time: 5 mins&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this post, I share some of my key thoughts from my LinkedIn Learning Future of Code Week episode discussing emerging languages. This session takes place on November 17th 2022. I was thrilled to be invited to share my thoughts with Marcus and Ray.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make sure to sign up to &lt;a href="https://bit.ly/foc-ep04"&gt;the event on LinkedIn!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bit.ly/foc-ep04"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qNc7GYqN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/foc_thumbnail.png" alt="Talk banner" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Session summary
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Emerging languages often try to change how developers solve problems, but they also often change the course of legacy languages. Programming languages like Go and Rust are not just inventing new ways to work with code, but also having a clear effect on new versions of existing languages. Will the new take over the old? Will the adjustments to existing programming languages be enough to stave innovation? Or, is it best at some point to start from scratch and rethink the foundation of how we approach programming?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Go does well
&lt;/h2&gt;

&lt;p&gt;Go has been hailed as a language that is &lt;strong&gt;easy to use and deploy&lt;/strong&gt;. There are a few reasons that should be top of mind when discussing this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Small syntax&lt;/strong&gt; - Go’s syntax has been made small by design, so that it’s easy to pick up and become productive with. One of the &lt;a href="https://golang.org/doc/faq#creating_a_new_language"&gt;purposes of the Go project&lt;/a&gt; was to simplify the act of programming and make it easier for developers to write statically typed code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static typing&lt;/strong&gt; - Go code is strongly, statically typed and compiled. The compiler catches a variety of bugs and allows for certain compile time performance optimizations. Go has built-in types for slices &amp;amp; maps which are easy to use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structs&lt;/strong&gt; - Go isn’t technically &lt;a href="https://golang.org/doc/faq#Is_Go_an_object-oriented_language"&gt;an object oriented language&lt;/a&gt;, but custom types are created using the &lt;code&gt;struct&lt;/code&gt; keyword. Structs can have methods attached to them in the same way objects do. They have been described as &lt;em&gt;lightweight objects&lt;/em&gt; since they do not support type inheritance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interfaces&lt;/strong&gt; - While Go doesn’t support type hierarchy, &lt;code&gt;interface&lt;/code&gt; types create reusable behaviours in a versatile and robust way according to the principle of &lt;a href="https://en.wikipedia.org/wiki/Composition_over_inheritance"&gt;composition over inheritance&lt;/a&gt;. Interfaces are &lt;em&gt;implicitly implemented&lt;/em&gt; on structs by the Go compiler. A struct can implement several interfaces just as long as it implements all the methods that they require. A common use case of interfaces is to wrap code coming from an external library into an interface on the side of &lt;em&gt;the calling code&lt;/em&gt; and only expose a subset of external functionality in the internal codebase.&lt;code&gt;interface{}&lt;/code&gt; is known as &lt;em&gt;the empty interface&lt;/em&gt;. It is satisfied by all types and is used as a parameter type by code that handles values of unknown type.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building and testing Go code&lt;/strong&gt; - The &lt;a href="https://golang.org/cmd/go/"&gt;go command&lt;/a&gt; exposes functionality for building &amp;amp; testing Go code. This is easy to use and comes with the default Go installation. The source code is built into a binary executable. Executables can be built for other targets/architectures using &lt;em&gt;cross compilation&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploying Go code&lt;/strong&gt; - The binary executable of Go source code contains not just application code, but also all the support code needed to execute the binary. This means that the Go executable can run without the need for system dependencies such as Go tooling to run on a new system, unlike other languages. Go executables can be &lt;em&gt;directly deployed&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generics&lt;/strong&gt; - recently added to Go, generics allows us to write better libraries that and data structures. From my experience, adoption of generics in production has been cautious. The Go team have put together &lt;a href="https://go.dev/blog/when-generics"&gt;talks and posts&lt;/a&gt; which discuss when &lt;em&gt;not&lt;/em&gt; to use generics, as they are not a silver bullet to better code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance &amp;amp; Concurrency
&lt;/h2&gt;

&lt;p&gt;Go is a &lt;strong&gt;fast and performant&lt;/strong&gt; language due to some very important optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inlining&lt;/strong&gt; - the Go compiler saves function calls by treating the body of a function as if it were part of the calling function. This has the trade off of increasing binary size, so Go only does so when it makes sense.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escape analysis&lt;/strong&gt; - Go implements this optimization which analyzes the scope of references to a value. If the references do not escape scope then they are saved on the &lt;em&gt;stack&lt;/em&gt; which is much faster and does not need to be garbage collected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage collection&lt;/strong&gt; - prevents memory leaks and has very low latency. The Go garbage collector is an intricate piece of code that you can check out on &lt;a href="https://tip.golang.org/doc/gc-guide"&gt;the Go Blog&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt; - Goroutines are multiplexed to a small number of OS threads. They are described as &lt;em&gt;lightweight threads&lt;/em&gt; with small stack sizes that are &lt;em&gt;cooperatively scheduled&lt;/em&gt; and managed by the Go runtime. Goroutines yield control at natural stopping points, making them more performant than kernel managed threads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the big advantages of using Go is the &lt;strong&gt;easier and more intuitive model of concurrency&lt;/strong&gt; that is central to the language:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Goroutines&lt;/strong&gt; - Functions/methods can be run concurrently to other functions/methods by starting a Goroutine using the &lt;code&gt;go&lt;/code&gt; keyword. They allow our application to use its resources optimally and perform more than one piece of work. All of the complex management and scheduling of goroutines is abstracted from the developer. Built on the concept of coroutines that is also used in Kotlin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channels&lt;/strong&gt; - Goroutines communicate through channels, which can be thought of as pipes through which data flows. Channels avoid data races by design as they maintain queues of goroutines and data themselves.The solid basics of Goroutines and channels can be combined to form a variety of basic and advanced concurrency patterns. Two notable concurrency patterns are &lt;a href="https://blog.golang.org/pipelines"&gt;pipelines&lt;/a&gt; and &lt;a href="https://golangbot.com/buffered-channels-worker-pools/"&gt;worker pools&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The future of Go
&lt;/h2&gt;

&lt;p&gt;In my opinion, the future of Go is bright ☀️:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Replacing legacy services&lt;/strong&gt; - due to its superior performance, engineering teams will continue to decompose monoliths and write new services in Go. In an increasing amount of companies, Go and microservices go together hand in hand. This de-facto choice is because Go’s&lt;a href="https://pkg.go.dev/net/http"&gt;net/http package&lt;/a&gt; makes writing REST APIs easy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased demand&lt;/strong&gt; - Go has recently “become a teenager” with its 13th birthday. It usage has been increasing and I would argue that it is moving away from emerging language status, as it has become adopted by major tech companies for mission critical jobs. You can see &lt;a href="https://go.dev/solutions/#case-studies"&gt;the full list of case studies on the Go blog&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compatibility promise&lt;/strong&gt; - &lt;a href="https://twitter.com/_rsc"&gt;Russ Cox&lt;/a&gt; gave a &lt;a href="https://youtu.be/v24wrd3RwGo"&gt;talk at GopherCon 2022&lt;/a&gt; about Go’s compatibility promise, which I really recommend. When updating to a new version of Go, you must compile your code again, but the team ensure that new versions do not break existing code. These guarantees make Go suited for writing Go code for the long term.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"Go is boring, and that's good!" - Russ Cox&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://youtu.be/v24wrd3RwGo"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nis-wG9s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://adelinasimion.dev/assets/boring_go.png" alt="GopherCon 2022: Russ Cox - Compatibility: How Go Programs Keep Working" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;Obviously, I’m a huge Go-lover and I believe that the language is here to stay. It’s got so many cool features the Go team do a great job to improve tooling and add new features. An often underrated aspect is &lt;strong&gt;community&lt;/strong&gt;. I’m proud to be part of the Go community, which is inclusive and welcoming. I think Gophers worldwide will continue to advocate for the language and grow.&lt;/p&gt;

&lt;p&gt;Join the &lt;a href="https://gophers.slack.com/"&gt;Gophers Slack&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>jobs</category>
      <category>go</category>
      <category>career</category>
      <category>interview</category>
    </item>
    <item>
      <title>Nevertheless, Adelina coded</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Thu, 03 Mar 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/nevertheless-adelina-coded-5cj3</link>
      <guid>https://dev.to/addetz/nevertheless-adelina-coded-5cj3</guid>
      <description>&lt;p&gt;In this post, I share some of my tech story as part of the &lt;a href="https://dev.to/devteam/share-your-2022-shecoded-story-to-donate-20-to-closing-the-tech-gender-gap-2hid"&gt;Dev.to SheCoded campaign&lt;/a&gt;, organised on the occasion of International Women’s Day 2022. I won’t be using names of individuals or companies in this retelling, but if you recognise yourself in the narrative, don’t reach out to me with an explanation or justification. Just DO BETTER THAN YOU’VE BEEN DOING!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, let’s begin.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Ymo8G7SGzk63YRqZai/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Ymo8G7SGzk63YRqZai/giphy.gif" alt="Do better" width="480" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Going to university
&lt;/h2&gt;

&lt;p&gt;Being a woman sometimes feels like drawing the short straw. Being an Eastern European woman on this wonderful continent 🇪🇺 sometimes feels like getting that already short straw broken in half. I am proud to be Romanian 🇷🇴 and I lived most of my life abroad, over two decades now. My family and I have lived through many prejudices for our accent, hair colour and “funny ways”.&lt;/p&gt;

&lt;p&gt;Throughout my entire life, I have had the good fortune of having the support of my mother, father and older brother. They have been my compass, my strength and my unwavering supporters. ❤️&lt;/p&gt;

&lt;p&gt;When I was 18, under the guidance of my family, I enrolled into the IT Engineering programme at the Technical University of Denmark in 2007. Yes, I did choose it because we thought it would be a lucrative career. When you are trying to make it in one of the most expensive places in Europe, you don’t have the luxury of discovering what your passion or dream job is.&lt;/p&gt;

&lt;h2&gt;
  
  
  My university “friends”
&lt;/h2&gt;

&lt;p&gt;I arrived at university wide eyed and excited. The first two years were absolutely brutal - writing code didn’t come naturally to me, the subject matter was terse and I had to put in a lot of hours of studying. However, my dilligence did eventually pay off and I started getting high marks.&lt;/p&gt;

&lt;p&gt;My university colleagues and “friends” made many sexist and callous remarks. One person flat out accused me of sleeping with the 60 year old male professor, another accused me of getting the grade because of the outfit I wore. Finally, when we were assigned a female professor, I was accused of getting the grade because we were both women.&lt;/p&gt;

&lt;p&gt;Some of my professors weren’t exactly stellar either. One of them told me that if I wore red nail polish again he would flunk me as he found it too “aggressive”… and while I was at it I should get rid of the makeup too!&lt;/p&gt;

&lt;p&gt;All of this had long term repercussions on me in the form of feeling out of place and like an impostor for much of my career. I have no doubt I would have quit if I hadn’t had my family in my corner, but I graduated with a high GPA and held my head high when I received my diploma. 🎓&lt;/p&gt;

&lt;p&gt;I wish I would have stood my ground when I was treated poorly, but most importantly, I wish the few people I was close to had stood up for me. I remember the silent faces alongside those who accused me in front of everyone. Don’t be a silent face in someone’s forever memory.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We must learn to be better allies for women in tech!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The missing female mentor
&lt;/h2&gt;

&lt;p&gt;After I finished my studies, I moved to London 🇬🇧 in 2014. I was fortunate to work with some great managers and engineers in my early career. They taught me technical fundamentals, supported me and helped me improve my self esteem.&lt;/p&gt;

&lt;p&gt;After some time, I was excited to work for my first female manager. She ended up being really tough: she told me off for “being mousy and batting your eyelashes”, she forced us to deliver subpar work for tight deadlines and she would take out her bad days on the team. I have since worked with many accomplished, truly amazing women. 🤩&lt;/p&gt;

&lt;p&gt;We often hold other women to the same prejudices that we have been held to our entire lives. I strive to be the female mentor I wasn’t able to find earlier in my career - to my friends, colleagues and anyone who reaches out to me.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As women in tech, we must be better role models and mentors for each other!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t say the M word
&lt;/h2&gt;

&lt;p&gt;Early in my career, I was often told what the maternity benefits packages were. They were probably trying to bolster my perception of the benefits package. I dismissed them with the wave of a hand. What’s this information to me? I’m young.&lt;/p&gt;

&lt;p&gt;As I approached my 30’s, I did become aware of my biological clock. The recruiters stopped mentioning their maternity packages. I became keenly aware that if I say the M word, &lt;em&gt;maternity&lt;/em&gt;, it would be potentially offputting to prospective employers. So, I stayed silent and signed contracts without asking.&lt;/p&gt;

&lt;p&gt;The UK has absolutely horrible &lt;a href="https://www.gov.uk/maternity-pay-leave"&gt;maternity leave&lt;/a&gt;, compared to many European countries. The law does not protect women’s income during maternity, so the private employer packages vary a lot here.&lt;/p&gt;

&lt;p&gt;I will speak out and ask about maternity packages in the future. We have to get rid of the stigma of women in their 30s asking for their rights to decent maternity protections.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We need to support diversity in tech with generous maternity AND paternity packages!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;Thanks for reading all about my tech story and thoughts! It means a lot to me that you cared enough to read it. ⭐️ All in all, I feel optimistic for the future. I do believe that things are improving, even though we are far from true gender equality. I will strive to be a positive force of change in tech.&lt;/p&gt;

&lt;p&gt;I will leave you with some family wisdom (I’m actually not sure if this is Romanian expression, or if it’s just a thing my mother says 🙈). Whenever I was sad or felt things were not going my way, my mother would say “the horses don’t die when the dogs wish them to” (&lt;em&gt;nu mor caii cand vor câinii&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The meaning of it is related to hunting. The horses and dogs take off in the hunting party. Obviously, horses have much more stamina than dogs. Naturally, the dogs tire first and exhaustedly wish the horses the worst, but they just keep running. 🐎 I suppose this is a roundabout way of saying &lt;em&gt;haters gonna hate&lt;/em&gt; 😆, but I like thinking of horses instead. 🐴&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Remember, you’re a majestic horse and you leave us all in your dust!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/ByTh8UTOcOXL2/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/ByTh8UTOcOXL2/giphy.gif" alt="Running horses" width="359" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>wecoded</category>
      <category>womenintech</category>
    </item>
    <item>
      <title>Tips for your first DevRel interview</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Sun, 20 Feb 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/tips-for-your-first-devrel-interview-214n</link>
      <guid>https://dev.to/addetz/tips-for-your-first-devrel-interview-214n</guid>
      <description>&lt;p&gt;In this post, I share what I learned about interviewing for a DevRel role, as I think there are a lot of folks who think they can’t achieve this role. This short list of Dos and Don’ts are really simple and easy to address. Make sure you follow them so you don’t lose out on any great DevRel opportunities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s make the most of those interviews!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.giphy.com/media/AYECTMLNS4o67dCoeY/giphy-downsized-large.gif"&gt;&lt;img src="https://i.giphy.com/media/AYECTMLNS4o67dCoeY/giphy-downsized-large.gif" alt="Job interview" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Interview tips
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;You &lt;strong&gt;DON’T&lt;/strong&gt; need to have a massive social media following to get your first DevRel role, but you &lt;strong&gt;DO&lt;/strong&gt; need to have a Twitter, GitHub and LinkedIn profiles with some relevant posts on them. 

&lt;ul&gt;
&lt;li&gt;As part of their initial screening, your future employer will look up your social media profile to see how you engage with the Tech community.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/eddiejaoude"&gt;Eddie Jaoude&lt;/a&gt; often explains on Twitter how to engage with others in a constructive and friendly way.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;DON’T&lt;/strong&gt; need to have a huge portfolio of talks, but you &lt;strong&gt;DO&lt;/strong&gt; need to have some current examples of material you could produce. 

&lt;ul&gt;
&lt;li&gt;Start a blog or write on &lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt; or &lt;a href="https://medium.com/"&gt;Medium&lt;/a&gt; to produce some writing samples. Personally, I prefer &lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt; between the two as the text editing is in markdown.&lt;/li&gt;
&lt;li&gt;If you do manage to speak at a conference, then you can use this as a video sample content. Otherwise, try to record a short tutorial or similar and upload to Youtube.&lt;/li&gt;
&lt;li&gt;I made this blog &lt;a href="https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll"&gt;using Jekyll and Github Pages&lt;/a&gt;, but if I were to start over I’d probably opt for &lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In my experience in interview process, everyone looked at my blog and read some writing samples, including the CTO, when I got to the final round.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DO&lt;/strong&gt; write a bespoke resume that highlights your DevRel adjacent experience. 

&lt;ul&gt;
&lt;li&gt;Engineers are ofen used to just sending round the same resume to all their roles, as it doesn’ really play that much of a role when getting selected for interviews. This is not the best tactic if looking to get your first DevRel role.&lt;/li&gt;
&lt;li&gt;I wrote up a special resume that highlighted my relevant experience more than just the technologies I worked with. You should include: your talk samples, your blog, any event organising experience (such as hackathons or other events) and any open source contributions you might have.&lt;/li&gt;
&lt;li&gt;This will help your future employer see your DevRel potential, even if you might not have full time DevRel experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DON’T&lt;/strong&gt; underestimate the power of the cover letter. 

&lt;ul&gt;
&lt;li&gt;Engineers are not used to writing cover letters, but I think they are a great opportunity to showcase your writing skills when applying for a DevRel role.&lt;/li&gt;
&lt;li&gt;I wrote a 1 page cover letter, where I explained why I wanted to be considered for the role. This gave me the option to explain my resume a bit more and offered some background about why I was interested in working at the company I was applying to. Again, everyone read this letter throughout the interview process.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DO&lt;/strong&gt; research the company you are applying to more than you might do for an engineering role. 

&lt;ul&gt;
&lt;li&gt;Most DevRel roles, including the ones where you will be joining an established DevRel team, require you to be a self starter with ideas.&lt;/li&gt;
&lt;li&gt;Make sure you research the company you are applying to and come up with some concrete ideas of how you can contribute to their program.&lt;/li&gt;
&lt;li&gt;I made some boards with screenshots from the company website where I jotted some ideas. In the end, I ended up sharing my boards during the interview. As I was quite nervous, my preparation helped me anchor myself and present my ideas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;It might be intimidating to move into a new role, such as DevRel, but don’t underestimate what you can bring to the table!&lt;br&gt;&lt;br&gt;
The field of DevRel is still growing and getting more established, so there is definitely place for you to get started in it.&lt;/p&gt;

&lt;p&gt;I’m happy to help with resume and cover letter reviews, so please don’t hesitate to reach out to me on &lt;a href="https://twitter.com/classic_addetz"&gt;Twitter&lt;/a&gt; if you need a second pair of eyes on these.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy interviewing &amp;amp; job hunting!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>techinterview</category>
      <category>devrel</category>
    </item>
    <item>
      <title>Unit testing in Go</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Mon, 31 May 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/unit-testing-in-go-4e16</link>
      <guid>https://dev.to/addetz/unit-testing-in-go-4e16</guid>
      <description>&lt;p&gt;Unit testing is paramount to writing stable, production ready code. In this post, we will talk a bit about what unit tests should cover and table driven tests in Go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s make Go tests our best friends!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.giphy.com/media/WDn21GO1KmpNK/giphy.gif"&gt;&lt;img src="https://i.giphy.com/media/WDn21GO1KmpNK/giphy.gif" alt="Best friends" width="480" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Basics
&lt;/h2&gt;

&lt;p&gt;For the sake of this testing discussion, let’s say we have created a new &lt;code&gt;Calculator&lt;/code&gt; that prints out formatted results and we want to ensure that it is working as expected.&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;type&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt; &lt;span class="k"&gt;struct&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;c&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="kt"&gt;int&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;if&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d+%d=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;y&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d%d=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;y&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;Go provides inbuilt support for testing using by using the &lt;a href="https://golang.org/pkg/testing/"&gt;testing package&lt;/a&gt;. A test is created by writing a function with a name beginning with &lt;code&gt;Test&lt;/code&gt; and being followed by the name of the method under test. The test signature takes exactly one parameter from the &lt;code&gt;testing&lt;/code&gt; package as seen below.&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;TestAdd&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameter &lt;code&gt;t&lt;/code&gt; that is provided in the function signature is used to signal errors to the test runner by using &lt;code&gt;Fail&lt;/code&gt; and &lt;code&gt;Errorf&lt;/code&gt;. One simple test for our &lt;code&gt;Add&lt;/code&gt; function can be:&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;TestAdd&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;want&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"2+3=5"&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;got&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="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&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;if&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;want&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;"Add(2,3) = %s; want %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;want&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;
  
  
  The unit under test
&lt;/h2&gt;

&lt;p&gt;Unit testing aims to test individual units or components of a piece of software. The purpose is to validate that each unit of the code performs as expected. In other words, unit tests are for verifying independent behaviours that we want to expose to outside of the component under test. Functions and structs are exported from Go &lt;strong&gt;packages&lt;/strong&gt; so unit tests should verify the functionality that your packages expose.&lt;/p&gt;

&lt;p&gt;In Go, tests live together with the source code in files that match the name of the source code file and ending in &lt;code&gt;_test&lt;/code&gt;. While not enforced, Go also encourages tests to live in a separate &lt;code&gt;_test&lt;/code&gt; package which has the dual purpose of making sure test functions do not leak into source code as well ensuring that only exported functions/behaviours are available in the test code. (&lt;em&gt;Note:&lt;/em&gt; Go does not allow multiple packages to live in the same directory, but &lt;code&gt;_test&lt;/code&gt; packages are exempt from this rule.)&lt;/p&gt;

&lt;p&gt;The eagle eyed readers might have noticed that the packages in the &lt;code&gt;Calculator&lt;/code&gt; example conveniently left out package names. We can now revisit this example and include our packages. The &lt;code&gt;Calculator&lt;/code&gt; can now live in the &lt;code&gt;nice_math&lt;/code&gt; package in a &lt;code&gt;calculator.go&lt;/code&gt; file.&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;nice_math&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="p"&gt;)&lt;/span&gt; 

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt; &lt;span class="k"&gt;struct&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;c&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="kt"&gt;int&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;if&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d+%d=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;y&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d%d=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;y&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 test can live in the &lt;code&gt;nice_math_test&lt;/code&gt; package in a &lt;code&gt;calculator_test.go&lt;/code&gt; file. The test then imports anything it uses from the &lt;code&gt;nice_math&lt;/code&gt; package explicitly.&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;nice_math_test&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;"github.com/addetz/nice_math"&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;TestAdd&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;want&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"2+3=5"&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;nice_math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;got&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="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&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;if&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;want&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;"Add(2,3) = %s; want %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;want&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;
  
  
  Table driven tests
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Table driven tests&lt;/strong&gt; have been growing in popularity amongst Go developers. This technique allows the same test setup to cover a variety of scenarios and ensure that the code is working as expected.&lt;/p&gt;

&lt;p&gt;The outline of a table driven test is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declare a test case structure that holds inputs and expected outputs for the function. Optionally, a name for the test case can be stored as well in the structure as well&lt;/li&gt;
&lt;li&gt;Construct an list/map with the test cases we want to test. If using a map, the name of the function can be the map key. &lt;em&gt;Note:&lt;/em&gt; I, personally, prefer to add the name of the test in the test case structure as it’s easier to understand conceptually than using the map key for the test name&lt;/li&gt;
&lt;li&gt;Range over the list/map of test cases and run any assertions necessary in a subtest using &lt;code&gt;t.Run&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can now expand our previous test to cover all of the logic of our calculator &lt;code&gt;Add&lt;/code&gt; method to test out those negative inputs that we had not looked at until 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;package&lt;/span&gt; &lt;span class="n"&gt;nice_math_test&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;"github.com/addetz/nice_math"&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;TestAdd&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;tests&lt;/span&gt; &lt;span class="o"&gt;:=&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;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
        &lt;span class="n"&gt;want&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"two positives"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&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="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"1+2=3"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"one positive one negative"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&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="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"1-2=-1"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;       
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"two negatives"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&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="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"-1-2=-3"&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="n"&gt;nice_math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tc&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;tests&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;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&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;got&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="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&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;got&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;want&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;"got %s, want %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;want&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;Subtests allow an itemised view of each test and their outcome, making it easy to detect and fix failures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=== RUN TestAdd
=== RUN TestAdd/two_positives
=== RUN TestAdd/one_positive_one_negative
=== RUN TestAdd/two_negatives
--- PASS: TestAdd (0.00s)
    --- PASS: TestAdd/two_positives (0.00s)
    --- PASS: TestAdd/one_positive_one_negative (0.00s)
    --- PASS: TestAdd/two_negatives (0.00s)
PASS

All tests passed.

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Assertions and libraries
&lt;/h2&gt;

&lt;p&gt;When it comes to testing, there are a few libraries that are worth mentioning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://golang.org/pkg/testing/"&gt;testing package&lt;/a&gt; comes with the standard library. It is easy to start with, but it quickly becomes tedious and repetitive when used on more complex code. It also provides the ability to write benchmarks for our functions as well&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/stretchr/testify"&gt;testify library&lt;/a&gt; provides easy to use assertions which come in super handy when asserting on objects. It also provides mocks for substituting dependencies (I’ve not really talked about mocks in this little post, as they deserve their very own discussion)&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/onsi/ginkgo"&gt;ginkgo library&lt;/a&gt; provides BDD style tests using the given/when/then pattern and is usually used with the &lt;a href="https://github.com/onsi/gomega"&gt;gomega matcher library&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;Unit testing in Go is easy when making use of table driven tests to test the behaviours that your Go packages export. The &lt;code&gt;testing&lt;/code&gt; package allows us to write subtests and write assertions for our code, allowing one test to cover multiple scenarios, while keeping traceability in test results.&lt;/p&gt;

&lt;p&gt;Other libraries such as &lt;code&gt;testify&lt;/code&gt; and &lt;code&gt;ginkgo&lt;/code&gt; provide synctactic sugar on top of the standard testing package, but many voices in the Go community promote writing simple functions and tests, for which the &lt;code&gt;testing&lt;/code&gt; package should be sufficient.&lt;/p&gt;

&lt;p&gt;I frequently use the &lt;code&gt;testify&lt;/code&gt; library for its assertions and mocks, but the structure of your tests and what they cover is more important than the library you choose for testing. I would definitely recommend starting out with just the standard testing library, keeping things simple for as long as possible and then moving to other alternatives as the need arises.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Go coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>code</category>
      <category>testing</category>
    </item>
    <item>
      <title>Go functions, closures and handlers</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Sat, 06 Feb 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/go-functions-closures-and-handlers-4in1</link>
      <guid>https://dev.to/addetz/go-functions-closures-and-handlers-4in1</guid>
      <description>&lt;p&gt;Estimated reading time: 7 mins&lt;/p&gt;

&lt;p&gt;While Go is not a functional language, functions are a central part of Go. They can be assigned to variables, passed as parameters and returned from other functions. This is known as &lt;em&gt;support for first class functions&lt;/em&gt; and it allows Go programmers to compose higher order functions and closures.&lt;/p&gt;

&lt;p&gt;Understanding these mechanisms can be a powerful addition to the tool belt of any programmer, so let’s take some time to explore the behaviour of Go functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s get functional and elegant!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.giphy.com/media/3ohuPGgXhIzUMMimQw/giphy.gif"&gt;&lt;img src="https://i.giphy.com/media/3ohuPGgXhIzUMMimQw/giphy.gif" alt="Functional and Elegant Spongebob" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Basics
&lt;/h2&gt;

&lt;p&gt;Functions are reusable code blocks, dedicated to performing well defined logic on inputs or &lt;em&gt;parameters&lt;/em&gt; and producing outputs or &lt;em&gt;return values&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In Go, functions are declared using the &lt;code&gt;func&lt;/code&gt; keyword. The naming convention is to use &lt;code&gt;camelCase&lt;/code&gt;. Unless exported, functions are available in the same package that they are declared into.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func myFirstFunction() {
    fmt.Println("This is my first function!")
}

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

&lt;/div&gt;



&lt;p&gt;Functions are allowed to take zero or more parameters and return zero or more outputs. The return types must be declared in the function signature.&lt;/p&gt;

&lt;p&gt;The function &lt;code&gt;hiBye&lt;/code&gt; below says hello and goodbye using 2 different return values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func hiBye(name string) (string, string) {
    return fmt.Sprintf("Hello, %s!", name),
        fmt.Sprintf("Goodbye, %s!", name)
}

func main() {
    hi, bye := hiBye("favourite reader")
    fmt.Println(hi)
    fmt.Println(bye)
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;main&lt;/code&gt; prints out these values to produce the output below. See this in action on the &lt;a href="https://play.golang.org/p/JB5bIV_gqFr"&gt;Go playground&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello, favourite reader!
Goodbye, favourite reader!

Program exited.

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

&lt;/div&gt;



&lt;p&gt;Go also supports &lt;em&gt;anonymous functions&lt;/em&gt;, which can be defined inline without having to be explicitly named. In the example below, &lt;code&gt;hiBye&lt;/code&gt; now only lives inside &lt;code&gt;main&lt;/code&gt;, but it will have the same output as before. See for yourself in the &lt;a href="https://play.golang.org/p/7KW81yKG8SX"&gt;Go playground&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func main() {
    hiBye := func(name string) (string, string) {
        return fmt.Sprintf("Hello, %s!", name),
            fmt.Sprintf("Goodbye, %s!", name)
    }

    hi, bye := hiBye("favourite reader")

    fmt.Println(hi)
    fmt.Println(bye)
}

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

&lt;/div&gt;



&lt;p&gt;Functions can also be &lt;em&gt;deferred&lt;/em&gt; using the &lt;code&gt;defer&lt;/code&gt; keyword. The deferred call’s arguments are evaluated immediately, but the function call is not executed until the surrounding function returns. The code below defers the call to &lt;code&gt;hiBye&lt;/code&gt; until &lt;code&gt;main&lt;/code&gt; finishes its work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func main() {
    hiBye := func(name string) {
        fmt.Printf("Hello, %s!\n", name)
        fmt.Printf("Goodbye, %s!\n", name)
    }

    defer hiBye("favourite reader")

    fmt.Println("Main says hello and goodbye!")
}

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

&lt;/div&gt;



&lt;p&gt;Due to the deferred function call, &lt;code&gt;main&lt;/code&gt; prints first, finishes, after which the greetings are printed. See this in action on the&lt;a href="https://play.golang.org/p/tABOudtvR2c"&gt;Go playground&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Main says hello and goodbye!
Hello, favourite reader!
Goodbye, favourite reader!

Program exited.

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Closures
&lt;/h2&gt;

&lt;p&gt;Closures are a special case of anonymous functions, which can be a little confusing for those not used to them, so they deserve a moment to investigate.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;closure&lt;/em&gt; is a function value that references variables from outside its body. The function may access and assign to the referenced variables; in this sense the function is &lt;em&gt;bound&lt;/em&gt; to the variables.&lt;/p&gt;

&lt;p&gt;The example below returns a closure, each referencing its own index and greet slice, thus allowing it to maintain state between invocations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func greet(greetings []string) func() string {
    index := 0
    return func() string {
        greet := fmt.Sprintf("%s!", greetings[index])
        index++
        return greet    
    }
}

func main() {
    his := []string{"Hello", "Salut", "Hej"}
    byes := []string{"Goodbye", "La revedere", "Farvel"}
    hi, bye := greet(his), greet(byes)
    for i := 0; i &amp;lt; len(his); i++ {
        fmt.Println(
            hi(),
            bye(),
        )
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;main&lt;/code&gt; prints out these values to produce the output below. See this in action on the&lt;a href="https://play.golang.org/p/XI1N_YcFZUT"&gt;Go playground&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello! Goodbye!
Salut! La revedere!
Hej! Farvel!

Program exited.

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Higher order functions
&lt;/h2&gt;

&lt;p&gt;As seen in the basics section above, Go functions can be passed around, returned and assigned to variables. This is particularly useful for constructing a function, but not immediately invoking it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Higher order functions&lt;/em&gt; are those functions composed from other functions. They can either accept a function as a type or return a function. Functions can be treated as any other value type, so composing higher order functions is easy and seamless.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;hiBye&lt;/code&gt; function can now be composed of 2 separate &lt;code&gt;greet&lt;/code&gt; functions and invoked only once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func print(name string, hi func(string) string, bye func(string) string) {
    fmt.Printf("%s\n%s\n", hi(name), bye(name))
}

func hiBye() (func(string) string, func(string) string) {
    hi := func(name string) string {
        return fmt.Sprintf("Hello, %s!", name)
    }
    bye := func(name string) string {
        return fmt.Sprintf("Goodbye, %s!", name)
    }
    return hi, bye
}

func main() {
    hi, bye := hiBye()
    print("favourite reader", hi, bye)
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;main&lt;/code&gt; prints out these values to produce the same output. See this in action on the&lt;a href="https://play.golang.org/p/Xank_7EAK8K"&gt;Go playground&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello, favourite reader!
Goodbye, favourite reader!

Program exited.

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handlers
&lt;/h2&gt;

&lt;p&gt;An interesting notable mention when discussing functions is in the context of building HTTP servers using the &lt;a href="https://golang.org/pkg/net/http/"&gt;&lt;code&gt;net/http&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An HTTP &lt;em&gt;handler&lt;/em&gt; is a function that runs in response to a request made to an HTTP server.&lt;br&gt;&lt;br&gt;
In Go, handlers are registered on server routes using the&lt;a href="https://golang.org/pkg/net/http/#ServeMux.HandleFunc"&gt;&lt;code&gt;http.HandleFunc&lt;/code&gt; convenience function&lt;/a&gt;. It sets up the default router in the &lt;code&gt;net/http&lt;/code&gt; package and takes a function as an argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))

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

&lt;/div&gt;



&lt;p&gt;A common way to write a handler is by using the&lt;a href="https://golang.org/pkg/net/http/#HandlerFunc"&gt;&lt;code&gt;http.HandlerFunc&lt;/code&gt; adapter&lt;/a&gt; on functions with the appropriate signature. Functions serving as handlers take a &lt;code&gt;http.ResponseWriter&lt;/code&gt; and a &lt;code&gt;http.Request&lt;/code&gt; as arguments. The response writer is used to fill in the HTTP response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type HandlerFunc func(ResponseWriter, *Request)

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;hiBye&lt;/code&gt; function explored so far can be easily converted to a handler function to serve the greetings explored so far. Note how the &lt;code&gt;hiBye&lt;/code&gt; function is passed to the &lt;code&gt;HandleFunc&lt;/code&gt; as a parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func hiBye(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Hello!\nGoodbye!\n")
}

func main() {
    http.HandleFunc("/hibye", hiBye)

    fmt.Println("Listening on :8090...")
    http.ListenAndServe(":8090", nil)
}

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

&lt;/div&gt;



&lt;p&gt;The full code can be seen in the&lt;a href="https://play.golang.org/p/1kCaXqrIdGi"&gt;Go playground&lt;/a&gt;, but it will need to be run locally and tested using &lt;code&gt;curl&lt;/code&gt;. The output should be as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl localhost:8090/hibye
Hello!
Goodbye!

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

&lt;/div&gt;



&lt;p&gt;The signature of the &lt;code&gt;HandlerFunc&lt;/code&gt; is pre-defined, so what would happen if the function needed more parameters passed to it? As before, it would be great to pass a name to the greeting, as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func hiBye(w http.ResponseWriter, req *http.Request, name string) {
    fmt.Fprintf(w, "Hello, %s!\nGoodbye, %s!\n", name, name)
}

func main() {
    http.HandleFunc("/hibye", hiBye("favourite reader"))

    fmt.Println("Listening on :8090...")
    http.ListenAndServe(":8090", nil)
}

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

&lt;/div&gt;



&lt;p&gt;This throws compilation errors because &lt;code&gt;HandleFunc&lt;/code&gt; is expecting a function parameter, but now the &lt;code&gt;hiBye&lt;/code&gt; function has been invoked with only one parameter. Oh dear, what a pickle!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run handlers.go
# command-line-arguments
./handlers.go:13:36: not enough arguments in call to hiBye
        have (string)
        want (http.ResponseWriter, *http.Request, string)
./handlers.go:13:36: hiBye("favourite reader") used as value 

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

&lt;/div&gt;



&lt;p&gt;While there are other solutions to this problem out in the wild, a common solution is to use a &lt;em&gt;wrapper function&lt;/em&gt; or &lt;em&gt;closure&lt;/em&gt; to pass the parameter to the &lt;code&gt;hiBye&lt;/code&gt; function. In this way, the returned function still conforms to the expected signature and the greeting gets its extra parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func hiBye(name string) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %s!\nGoodbye, %s!\n", name, name)
    }
}

func main() {
    http.HandleFunc("/hibye", hiBye("favourite reader"))

    fmt.Println("Listening on :8090...")
    http.ListenAndServe(":8090", nil)
}

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

&lt;/div&gt;



&lt;p&gt;The full code can be seen in the&lt;a href="https://play.golang.org/p/7nTl51S9tfK"&gt;Go playground&lt;/a&gt;, but it will need to be run locally and tested using &lt;code&gt;curl&lt;/code&gt;. The output should be as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl localhost:8090/hibye
Hello, favourite reader!
Goodbye, favourite reader!

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;That’s it for now. I’ve covered a lot of ground, but a few key points to remember are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go functions can be assigned to variables, passed as parameters and returned from other functions&lt;/li&gt;
&lt;li&gt;Functions can be anonymous. This means they are declared inline and are not explicitly named&lt;/li&gt;
&lt;li&gt;Closures are anonymous functions that are bound to variables outside of their body&lt;/li&gt;
&lt;li&gt;Higher order functions are composed from other functions. They can either accept functions as a type or return functions&lt;/li&gt;
&lt;li&gt;Handlers are functions that run in response to a request made to an HTTP server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having a good understanding of functions can help solve a wide variety of problems through composition. I hope this post gave you an insight into the wonderful world of Go functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Go coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>functions</category>
      <category>closures</category>
      <category>code</category>
    </item>
    <item>
      <title>Dealing with interview rejection</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Sun, 24 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/dealing-with-interview-rejection-1h0j</link>
      <guid>https://dev.to/addetz/dealing-with-interview-rejection-1h0j</guid>
      <description>&lt;p&gt;Estimated reading time: 4 mins&lt;/p&gt;

&lt;p&gt;The tech industry has &lt;a href="https://devskiller.com/attrition-rate-in-tech"&gt;high turnover and attrition rates&lt;/a&gt;. Engineers get out on the job market more often and spend more time preparing for and going through interviews than other sectors. On the flip side, engineers also have to deal with more interview rejections.&lt;/p&gt;

&lt;p&gt;While it’s always painful to be rejected or not achieve a goal we worked hard for, rejections are a great way to learn. In this post, I share some of my ways to deal with the bitter pill that is interview rejection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s turn that frown upside down! :)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.giphy.com/media/ehvBqPh1p0r9S/giphy.gif"&gt;&lt;img src="https://i.giphy.com/media/ehvBqPh1p0r9S/giphy.gif" alt="Frown" width="320" height="320"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Turn that frown upside down!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The subjective and imperfect interview process
&lt;/h2&gt;

&lt;p&gt;Before getting into handling interview rejection, let’s discuss the interview process itself. This will set the basis of what the rejection really means.&lt;/p&gt;

&lt;p&gt;Typically, the technical interview process &lt;em&gt;aims&lt;/em&gt; to assess:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ability to contribute to technical projects&lt;/strong&gt; : each team will be working with a different tech stack and solving their own unique set of problems. The interview process &lt;em&gt;should&lt;/em&gt; (if thoughtfully designed!) pose coding challenges which are representative of what the team works on. The technical question is therefore skewed to look for a certain experience and profile&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cultural fit&lt;/strong&gt; : even brilliant, genius engineers need to fit into their prospective team. The process does not focus on the technical solution only, it will (and should!) include an assesment of communication skills and team fit. Each team has its own practices and idiosyncracies, so interviewers will look for signals which reflect the team’s practices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seniority and expertise&lt;/strong&gt; : the team will be looking for a specific level of seniority as well as technical skill. Depending on the role, the interview process might assess attitude to learning and development as well as mentoring style to ensure that it fits with the expectations of the role they are trying to fill. A candidate that does well on the technical task might still be unsuccessful if they do not perform at the job role’s level of seniority&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interview process is a skewed and subjective process that, by design, can only assess technical ability in the frame of a single team’s work and expectations. Assessments of team fit are predictions that interviewers make on the basis of a relatively short interaction with the candidate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind that the process is far from perfect and don’t take rejections personally!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the most of interview rejection
&lt;/h2&gt;

&lt;p&gt;Now that I’ve set the scene for what the rejection really means, it is time to look at how to make the most of an interview rejection.&lt;/p&gt;

&lt;p&gt;Here are my tips to making the most out of interview rejections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Request written feedback&lt;/strong&gt; : most recruiters will want to give interview feedback on the phone to give a more personal touch to the process. Hearing the feedback can be emotional, making it difficult to remember the details of what was said. Make sure to request written feedback from the interviewers themselves instead of the recruiter’s short verbal version. This might take a while to receive, but most recruiters will be happy to help candidates improve&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solve the interview problems again&lt;/strong&gt; : take the time to solve the interview problems again at home, making sure to fix any issues of the interview solution. This will empower and fill in any immediate technical gaps. Who knows? The same problem might come up at another interview in the future&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use it as constructive, free feedback&lt;/strong&gt; : turn the power dynamic back and take the interview rejection as constructive feedback instead. I’ve learned where my technical gaps are and how to be better at communicating from interviews. Rejections are a great learning tool, so use them to direct and adjust interview preparation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Think of interviewing as a skill in itself&lt;/strong&gt; : practice is important when picking up any skill. Treat all interviews as practice, where learning is the primary objective and getting an offer is the icing on the cake. No matter the amount of preparation and studying, the proof is in the pudding and there is no substitute for actually taking the leap and getting out there&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the interview process to judge the employer&lt;/strong&gt; : the interview questions are one of the strongest signals a candidate can get about their prospective employer, giving insight into what they find important and what working there might be like. If these questions don’t align with the candidate’s interests and experiences, then they might not be a suitable future employer, regardless of whether the interview is a success or not&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;Remember, interview rejections happen to everyone!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interviewing is more like dating than an academic exam.&lt;/strong&gt; An interview rejection simply means that the candidate was perceived as not fitting well into the projected expectations of that team, not that they are not a good engineer. Just like dating, it’s all about two sides matching up what they’re looking for.&lt;/p&gt;

&lt;p&gt;It’s important not to internalise rejection as anything more than it is. It is not a reflection of general technical ability, but a subjective evaluation of the candidate based on a skewed process. Take whatever constructive feedback the interview provides, learn from it and then move on, stronger and better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy interviewing &amp;amp; job hunting!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>jobs</category>
      <category>career</category>
      <category>interview</category>
    </item>
    <item>
      <title>A little more code review please!</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Sun, 10 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/a-little-more-code-review-please-44ad</link>
      <guid>https://dev.to/addetz/a-little-more-code-review-please-44ad</guid>
      <description>&lt;p&gt;Most of us working in software engineering can agree that code reviews are important and should be a priority, no matter how busy we get. However, I have seen my fair share of teams that have struggled to carry out their best code review intentions into sustained working process.&lt;/p&gt;

&lt;p&gt;In this post, I will discuss some code review best practices for both authors and reviewers, so that we can make the process as efficient and enjoyable as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A little less conversation, a little more code review please!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/WWVMXLSS1cA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Code review, what is it good for?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Code_review"&gt;Code review&lt;/a&gt;, or &lt;em&gt;peer code review&lt;/em&gt;, is the process through which the &lt;strong&gt;code author&lt;/strong&gt; gets their colleagues/peers to check their work. The author typically submits a &lt;strong&gt;pull request(PR)&lt;/strong&gt; which contains the implementation of all the changes they are proposing. The author’s colleagues typically read and make recommendations on the implemented code changes becoming &lt;strong&gt;code reviewers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As mentioned in the intro, everyone seems to agree that code reviews are generally a good idea and they have been thoroughly discussed in &lt;a href="https://leanpub.com/whattolookforinacodereview"&gt;articles&lt;/a&gt;, &lt;a href="https://smartbear.com/learn/code-review/why-review-code/"&gt;blogs&lt;/a&gt; and &lt;a href="https://www.amazon.co.uk/Implementing-Effective-Code-Reviews-Maintain-ebook/dp/B08HGLTRPM/"&gt;books&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A few of the benefits of code reviews are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Better code quality&lt;/strong&gt; : code reviewers can find defects or edge cases that the author has not considered before they are deployed to production. The cost of code review time is infinitesimal compared to the potential cost of a production outage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Knowledge sharing&lt;/strong&gt; : engineers of all levels benefit from code reviews: newbies learn how to solve complex problems from the more experienced members, while experienced members stay in the loop with all the changes that the team is making and prevent knowledge silos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increase code ownership&lt;/strong&gt; : the team gets a sense of solidarity, responsibility and ownership for the whole codebase if the work is collectively agreed on. Code reviews offer the opportunity for everyone in the team to propose solutions and discuss the best solutions to problems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ensure maintainability&lt;/strong&gt; : once the team reach a mutually agreed solution, they can also ensure that the codebase is documented and maintainable. The code review process itself ensures that other engineers understand the work of the author, thus ensuring maintainability of the codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code reviews are a very worthwhile time investment and are an essential tool for any team delivering stable production software. &lt;em&gt;Unlike war, code reviews are good for many things!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/01-2pNCZiNk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Code review, where did we go wrong?
&lt;/h2&gt;

&lt;p&gt;Some ways I have seen the code review process go wrong are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dramatically slowing down code delivery&lt;/strong&gt; : code changes can be stuck awaiting for review for a long time and slow down delivery. A PR can be stuck waiting for review for days. Finally, the review is rushed and the code is merged to production at the last minute&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Becoming a box ticking exercise&lt;/strong&gt; : code changes are not reviewed in depth and in a constructive way. The code review becomes a box ticking exercise where all reviews are automatically approved, rendering the code review process irrelevant&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not sharing with the whole team&lt;/strong&gt; : team members approve each others’ reviews without sharing them with everyone. Team members are not aware of all the changes made to the codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When it goes wrong, the code review process cannot give us the benefits discussed in the previous section. Code reviews then become a cumbersome annoyance that we avoid and ignore. &lt;em&gt;When code reviews go wrong, it is all our fault!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/dEw_t9jR8Yc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  I’m gonna write you a PR!
&lt;/h2&gt;

&lt;p&gt;Having looked at the benefits of code reviews and how they can go wrong, it’s time to discuss what we can do as code authors to make the process smooth and enjoyable for code reviewers. The author starts the whole process and has a vested interest in making sure reviewers can make the best recommendations for their work.&lt;/p&gt;

&lt;p&gt;In my experience, code authors should ensure that they:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Easily share proposed code changes&lt;/strong&gt; : the proposed code changes should be easy to access and read. I mentioned earlier that code changes are typically shared by raising a pull request(PR) and sharing it with reviewers. PRs are hosted on Github, or a similar service, where the reviewers can view and comment. While this is common practice, simply extracting a diff file and sharing it would do the trick as well, as what is most important is giving reviewers a way to easily see the proposed code changes at a time that suits them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write meaningful commit messages&lt;/strong&gt; : commit messages are the first thing that code reviewers see when they start the review. They should be well written and offer context to what the changes are aiming to achieve. They should also link to any tickets/issues they are fixing to ensure traceability. &lt;a href="https://golang.org/doc/contribute.html#commit_messages"&gt;Go’s contribution guidelines to good commit messages&lt;/a&gt; offers some very good recommendations on commit messages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep code changes small&lt;/strong&gt; : it is tempting to extend scope and implement several things in the same code commit. This is a tendency that is common with less experienced engineers, and a mistake I often made in the beginning of my career. Large code changes are hard to test, stabilize and review. Remember that a code commit does not have to fix a whole ticket. A single code change should be a small, testable piece of work that achieves only one single piece of functionality. It should be complete, but should not attempt to do more than its small scope. This will allow reviewers to focus on the one change and reduce review time, making it easier to fit into their schedule&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allow the entire team to see the proposed change&lt;/strong&gt; : make sure that code changes are shared with the team and assigned to appropriate code reviewers. Share the code change on the correct channels and ensure everyone in the team is aware of the change. Reviewers with the correct expertise should be assigned for review, going outside the team if necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code changes which are well defined, well tested and provide sufficient context are a joy to review. &lt;em&gt;As long as your code changes follow these simple rules, you can write me a PR any time!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/qi7Yh16dA0w"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  These PRs are made for reviewing!
&lt;/h2&gt;

&lt;p&gt;Finally, once good code changes are submitted for review, it is time for the code reviewers to shine and do their best work! The code review itself should be an enriching and constructive process for all.&lt;/p&gt;

&lt;p&gt;In my experience, code reviewers should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Make it a priority to unblock others&lt;/strong&gt; : in essence, once the author has submitted their code change for review, the work is blocked until reviewed. It can be difficult to balance delivering own work together with code reviews, but code reviews should be the number 1 priority of the entire team. Unblocking others should always take precedence to delivering own work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offer meaningful constructive comments&lt;/strong&gt; : code reviewers should ensure they take the time to write meaningful, well formulated and constructive comments that empowers the author and helps them grow. Comments should take into account the level of experience and knowledge of the author, ensuring that they offer easy to follow guidance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request explicit documentation&lt;/strong&gt; : code reviewers should set aside their own experience with the codebase and request explicit documentation which might be useful for a newcomer, even if they themselves don’t need it. This ensures that code changes are maintainable and well documented&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agree on a team wide review turnaround time&lt;/strong&gt; : my recommendation is that the team agree on a code review turnaround time and collectively enforce it, to avoid code changes being blocked awaiting for review. Once this is agreed, team members can block their calendars accordingly to ensure that they have the appropriate bandwidth to deliver these reviews in the agreed time frame&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code reviewers play a crucial role in shipping stable features at speed. Prioritize unblocking others and &lt;em&gt;review these these PRs that are made for reviewing.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/SbyAZQ45uww"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;Code reviews are such an important engineering tool: helping us deliver stable software, learn from each other and ensure we are shipping the best solutions. Engineers frequently change hats between code author and code reviewer during daily work, so keeping in mind what to do to make the other person’s job easier will ensure that the process remains efficient and enjoyable for everyone involved.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this roundup of code review best practices with a musical twist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy code reviewing!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>programming</category>
      <category>github</category>
    </item>
    <item>
      <title>Why do you like Go?</title>
      <dc:creator>Adelina Simion 🥑</dc:creator>
      <pubDate>Thu, 31 Dec 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/addetz/why-do-you-like-go-3353</link>
      <guid>https://dev.to/addetz/why-do-you-like-go-3353</guid>
      <description>&lt;p&gt;I was asked this question - “Why do you like Go?” - during several job interviews. The question itself is not tough, but it is broad and full of opportunities to trip up. It’s difficult to distill your thoughts into a coherent answer in a high pressure situation.&lt;/p&gt;

&lt;p&gt;I’m going to use this post to nail down an answer to this dreaded question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s Go!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.giphy.com/media/dW6SH3HDxZjbzUT0kF/giphy.gif"&gt;&lt;img src="https://i.giphy.com/media/dW6SH3HDxZjbzUT0kF/giphy.gif" alt="Go cactus" width="600" height="600"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Let's Go!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the question means
&lt;/h2&gt;

&lt;p&gt;The question is ambiguous, but it has been posed to me in this form. Even though I write Go code daily, I wouldn’t say I have any personal feelings of “like” towards it.&lt;/p&gt;

&lt;p&gt;The question is meant to be a conversation starter about the usage and strengths of Go. In my experience, the answer should touch upon the broad areas presented below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing &amp;amp; deploying Go code
&lt;/h2&gt;

&lt;p&gt;Go has been hailed as a language that is &lt;strong&gt;easy to use and deploy&lt;/strong&gt;. There are a few reasons that should be top of mind when discussing this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Small syntax&lt;/strong&gt; - Go’s syntax has been made small by design, so that it’s easy to pick up and become productive with. One of the &lt;a href="https://golang.org/doc/faq#creating_a_new_language"&gt;purposes of the Go project&lt;/a&gt; was to simplify the act of programming and make it easier for developers to write statically typed code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static typing&lt;/strong&gt; - Go code is strongly, statically typed and compiled. The compiler catches a variety of bugs and allows for certain compile time performance optimizations. Go has built-in types for slices &amp;amp; maps which are easy to use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structs&lt;/strong&gt; - Go isn’t technically &lt;a href="https://golang.org/doc/faq#Is_Go_an_object-oriented_language"&gt;an object oriented language&lt;/a&gt;, but custom types are created using the &lt;code&gt;struct&lt;/code&gt; keyword. Structs can have methods attached to them in the same way objects do. They have been described as &lt;em&gt;lightweight objects&lt;/em&gt; since they do not support type inheritance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interfaces&lt;/strong&gt; - While Go doesn’t support type hierarchy, &lt;code&gt;interface&lt;/code&gt; types create reusable behaviours in a versatile and robust way according to the principle of &lt;a href="https://en.wikipedia.org/wiki/Composition_over_inheritance"&gt;composition over inheritance&lt;/a&gt;. Interfaces are &lt;em&gt;implicitly implemented&lt;/em&gt; on structs by the Go compiler. A struct can implement several interfaces just as long as it implements all the methods that they require. A common use case of interfaces is to wrap code coming from an external library into an interface on the side of &lt;em&gt;the calling code&lt;/em&gt; and only expose a subset of external functionality in the internal codebase.&lt;code&gt;interface{}&lt;/code&gt; is known as &lt;em&gt;the empty interface&lt;/em&gt;. It is satisfied by all types and is used as a parameter type by code that handles values of unknown type&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First class functions&lt;/strong&gt; - Go functions can be assigned to variables, passed as parameters to other functions and returned from other functions. This is known as &lt;em&gt;support for first class functions&lt;/em&gt;. This allows Go programmers to compose higher order functions and closures, which are particularly useful for &lt;em&gt;dynamic programming&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building and testing Go code&lt;/strong&gt; - The &lt;a href="https://golang.org/cmd/go/"&gt;go command&lt;/a&gt; exposes functionality for building &amp;amp; testing Go code. This is easy to use and comes with the default Go installation. The source code is built into a binary executable. Executables can be built for other targets/architectures using &lt;em&gt;cross compilation&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploying Go code&lt;/strong&gt; - The binary executable of Go source code contains not just application code, but also all the support code needed to execute the binary. This means that the Go executable can run without the need for system dependencies such as Go tooling to run on a new system, unlike other languages. Go executables can be &lt;em&gt;directly deployed&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance of Go
&lt;/h2&gt;

&lt;p&gt;Go is a &lt;strong&gt;fast and performant&lt;/strong&gt; language due to some very important optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inlining&lt;/strong&gt; - the Go compiler saves function calls by treating the body of a function as if it were part of the calling function. This has the trade off of increasing binary size, so Go only does so when it makes sense&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escape analysis&lt;/strong&gt; - Go implements this optimization which analyzes the scope of references to a value. If the references do not escape scope then they are saved on the &lt;em&gt;stack&lt;/em&gt; which is much faster and does not need to be garbage collected&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage collection&lt;/strong&gt; - prevents memory leaks and has very low latency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt; - Goroutines are multiplexed to a small number of OS threads. They are described as &lt;em&gt;lightweight threads&lt;/em&gt; with small stack sizes that are &lt;em&gt;cooperatively scheduled&lt;/em&gt; and managed by the Go runtime. Goroutines yield control at natural stopping points, making them more performant than kernel managed threads&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Concurrency in Go
&lt;/h2&gt;

&lt;p&gt;One of the big advantages of using Go is the &lt;strong&gt;easier and more intuitive model of concurrency&lt;/strong&gt; that is central to the language:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Goroutines&lt;/strong&gt; - Functions/methods can be run concurrently to other functions/methods by starting a Goroutine using the &lt;code&gt;go&lt;/code&gt; keyword. They allow our application to use its resources optimally and perform more than one piece of work. All of the complex management and scheduling of goroutines is abstracted from the developer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channels&lt;/strong&gt; - Goroutines communicate through channels, which can be thought of as pipes through which data flows. Channels avoid data races by design as they maintain queues of goroutines and data themselves&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency patterns&lt;/strong&gt; - The solid basics of Goroutines and channels can be combined to form a variety of basic and advanced concurrency patterns. Two notable concurrency patterns are &lt;a href="https://blog.golang.org/pipelines"&gt;pipelines&lt;/a&gt; and &lt;a href="https://golangbot.com/buffered-channels-worker-pools/"&gt;worker pools&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;Since the answer to this broad question had a lot to cover, I have only given some brief headline answers to each topic. In an interview setting, you should be prepared to be asked to delve into more detail on any topics of particular interest. I am not be able to provide this level of detail in this post, but I have left some further reading links below which should be useful.&lt;/p&gt;

&lt;p&gt;Go is particularly suited for building high volume, scalable, performant web applications. It has been &lt;a href="https://insights.stackoverflow.com/survey/2020#technology-most-loved-dreaded-and-wanted-languages-loved"&gt;gaining lots of popularity in the Dev community&lt;/a&gt; and has been adopted by big players such as Google, Uber and Netflix. I hope this blog post will help you answer questions about the benefits and strengths of Go, whether in an interview or not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Go coding!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://golangbot.com/interfaces-part-1/"&gt;Interface&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://golangbot.com/first-class-functions/"&gt;First class functions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dave.cheney.net/2014/06/07/five-things-that-make-go-fast"&gt;Five things that make Go fast&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.golang.org/ismmkeynote"&gt;Getting to Go: The Journey of Go’s Garbage Collector&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://golangbot.com/concurrency/"&gt;Introduction to Concurrency&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://golang.org/doc/articles/wiki/"&gt;Writing Web Applications&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>interview</category>
      <category>career</category>
    </item>
  </channel>
</rss>
