Conf42 Golang 2021 - Online

Ultimate Guide to Golang Development for Beginners

Video size:

Abstract

A talk about easy start with Golang development with production grade examples and tools

In this talk I will try to show how to start Golang Development with production grade best practices. You will learn the answers of “How to do environmental/project setup?”, “How to test your projects”, “What kind of tools you need to use to ship your application?”, etc....

On each section, there will be a mapping from other languages to have better insight.

Summary

  • Hussain Hussain: In this session I will try to provide some best practices about Golang in theory. With Go modules you can implement modular applications plus you can manage your dependencies. At the end we will see how to build an artifact out of these Golang projects to be used inside CI and CD platforms.
  • There is no for each function in Golang, but you can simulate it. In golden if you define something but not use it, the compiler will start to complain about it. If you need mock related operations, you can use mockery which is a third party library. You can also use Golang mock in your system.
  • Golang has built in tools to generate artifacts based on our distribution. You need to know how much part of your code base production code is covered by best. When you provide dash cover profile and some file, it will put the report in this file. Let's have a look a couple of demo by using these theoretical informations.
  • What about functions? Let's switch to functions. Here I define another directory functions. What about testing? In my functions package I am creating a file called functions test. If sum is not equal to parameter expected, then you can say t error f. And what about coverage? Just select this one and run with coverage.
  • Let's try to build an artifact. In my case this will be, let's say the conf 42. When you do a build operation, you will see binary will be generated. What about using this one in the containerization? Build a docker image and then generate something.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Hi everyone, my name is Hussain, I am software development teammate of hellocast cloud. In this session I will try to provide some best practices about Golang in theory and I will do a demo about what we see inside the theoretical information. So as an outline we will see what is Golang, we will see how to set up development environment, couple of Golang examples and by using this examples how to write best and at the end we will see how to build an artifact out of these Golang projects to be used inside CI and CD platforms. Golang is a statically typed compiled language and it is originally designed by Robert Gresimer and Rob pike and Ken Thompson while they are working at Google. This is very similar to C language but there is a memory safety and the garbage collection stuff in this language. Remember CNC times you need to alloc on melloc memory in order to do some operations, but here you are free to do anything without touching on the memory part. And if you want to deep dive any kind of topic in Golang you can just refer the landing page because it is golang.org. Before writing code you need to download the Golang binary in your system. You can just go to Golang download page and download your distribution based on your operating system. In my case I'm using macOS and I will download this macOS distribution if you are preparing a project creating a project these project dependencies are a very important topic. In Golang there is a system which is called Go modules. With Go modules you can implement modular applications plus you can manage your dependencies. In the examples you see I say go mod in it and my version control system URL it will create a modular application. Of course it is empty. There will be only one file which is called Go mod file. And here after Gomode init you see it is dependent to GitHub.com, my outdoor name and my repository. But you can use GitLab, BitBucket or maybe if you have a custom version control system service you can also use that inside the Go module. When you have a look at module file you will see a module information calling version and if you have dependency you can see also dependent sections by using required keyword. In order to see all the dependencies you can say goal list m all you will see your exact dependency plus the recursive dependencies needed by this library. Okay, you know how to use Golang, I mean the distribution and you know how to generate an empty project. Now you can select one of your favorite ides, but as an example, if you are using Vim terminal, you can use Vimgo plugin. If you are using intelligence products you can use Golang or you can use vs code as an alternative. If you are using Vim terminal, then by using go ran command you can just run your application. If you are using Golan, you can define a run configuration to run your project in vs code. You can run your application by using control plus f five. So this is very fresh start about writing something and just running your application to see what's going on. When you create a resource file in Golang, it will start by a package statement. Here I am saying that my package name is main and right after that I have some import statements. I depend on context package, fmt package and GitHub package. Here, if you define your package name as main, this will be an executable rather than a library. For example, when you have a math package, it will be a library package. Then you can put your functions inside it. But in our case this is just for executable very initial principle of any kind of programming language. Variable declaration here in the first example you see I declare a variable. I am saying that count is a variable and it is type. It's integer. The second line you see I am assigning some value to it. Count is equal to five. When you say limit colon is equal to 15. You are just declaring and assign a value to a variable. So this is also known by calling language. In this following example you see I am defining a slice which is called list arrays relies on other languages. It starts with square brackets, and I am saying that this will be a slice of integer and I put some values inside it. In the following example you see there is a nums slice, but this time I am allocating a slice size. So I'm saying that there will be an integer slice, but its size will be three, and the very first value, the zero index value will be one. In my case. Also, you can define two dimensional slices here and the value is flot 54. As the final example you see I am defining a map. It is a key value store. In my case, keys is data, type is integer, the value will be string. Let's say that this is the student information map. The key is student id and the value is student name. In order to declare a function in Golan you can use funk keyword and it's followed by a name. Here sum. We open the parentheses and put arguments inside it. A and b the return type is integer and of course you provide your return function body. In the second example very same, but the return type is a bit different. For example, if you have scala before you remember the tuples, so sometimes you may need to return multiple values. In my case I just wanted to state x and y coordinated separately. Here in the third example, you see there is a do something. In do something, the function name starts with a lowercase letter. That means this function will be a private the first two will be exposed to outside, but third one will not be exposed to outside. When it comes to usage, you see I am saying functions sum provide your arguments and it will return a value. Just assign a variable. Another example, get coordinates. You see, it returns two values and I am using x and y in order to use different references to these returned values. Control structures are very important to define your business logic, right? You decide on something. I define an if function. Here it takes a parameter category. If category is shoes, I print show. Otherwise I print not a show. The main difference between other languages is there is no parenthesis right beside the if statement. In the switch statement, very similar case, you provide your variable and switch statement followed by one or more cases. And at the end there is a default case if it is a pc. If device is a pc, just stay at home. If it is a laptop, you can go outside. What about for loops in Golang? Again there is no parenthesis. I starts with zero up to ten v increment I by one. Here, if the number is divided by two, I am continue. I'm saying continue. That means just skip to next iteration without printing the current number. And in the second example I define a counter variable with initially initialized by zero and there is no statement beside the four. That means this is an infinite loop, right? And inside this infinite loop I am saying that if the counter is equal to ten, just break. That means just break the loop, otherwise it will increment counter by one. Here there is no for each function in Golang, but you can simulate it. I defined a number slice that contains four numbers. Inside the for statement there is a key value pairs. But why there is an underscore in the key part? Because I am not interested in the key part. So in golden if you define something but not use it, the compiler will start to complain about it. So if you are not interested in it, just put an underscore. You say range numbers and in this time you will get number. In iteration we are just printing the specific number inside the slice. In the second example I have a map. This time it is string string key string value string. It is simple, a country code and the country name keystore here. This time I am interested in both key and the value part called country and I am printing the code and country at the same time into the standard output. So I have functions, variables, etc. Let's try to test this one. In Golang you can use built in packages like testing, but also you can use testify which is a third party library. If you like more assert like operations. If you need mock related operations, you can use mockery which is a third party library. Also you can use Golang mock in your system. So I will not deep dive into mock part because it really deserves a separate session. But when it comes to unit test part, let's try to test a function which is called fibonacci. I have a Fibonacci function. It accepts a number as a parameter and it tells you what is the value at that number index. So here I am injecting the testing t reference to my function and keep in mind that my function name start with test. This is the naming convention. If the result is not 610 it will start to complain about I want 610 but got another result. But what about if you want to test this function fibonacci with different kind of multiple inputs, then you can use test table here. Inside my test fibonacci in batch function I am defining a struct slice of struct and it accepts two parameters, input and expected. Here I have five scenarios, test cases and inside the for loop I am iterating these parameters calling Fibonacci function. I am trying to verify if actual is equal to parameter or not. Otherwise it will start to complain about this one. You write best, but what about coverage? You need to know how much part of your code base production code is covered by best. Right here. When you say go best provide the test folder and when you say dash cover it will calculate the coverage. When you provide dash cover profile and some file, it will put the report in this file. So this is very useful, especially if you want to do further operations. Something like generate HTML output. Like operations. Okay, we generate this coverage because they are already being used inside the CI systems, right? For example, if you are using sonar, then this coverage file will be used for sonar to analyze your code base. Maybe put as some kind of thresholds in CI CD part. I will not talk about something like Jenkins maybe or GitHub Excel or something like that. I will try to give information about the very minimum unit of the CI CD systems, the artifacts. Golang has built in tools to generate artifacts based on our distribution. So in order to see supported disk platforms in Golang you can use go tool disk list. So in the table you will see your supported operating system and the architecture. In my case I'm using macOS. The value is Darwin AMD 64. In order to build a project to generate some binary you can provide your operating system and architecture and when you say go build, the binary will be generated based on these distribution parameters. So why do you need this binary? Because it is very popular inside the contain world. For example, I create a docker file and I put some contents inside it. So here I am saying that I will drive my docker image from Golang and I provided alias as builder. I create a folder, I make my folder to USRSRc app. I copy all of project files to the docker context. I download my dependencies by gomodownload and generate my binary. But this time I'm providing all parameter to change the output name. This is the first stage, but in the second stage I am driving my docker image from scratch which is the zero sized docker image. I am copying the binary generated on the first phase to my stage. Then I am providing this hello binary as an entry point into this image. So we are calling this strategy as multi stage docker. Bill I believe that the theoretical information was enough for this session. Let's have a look a couple of demo by using these theoretical informations. Let me open my terminal first I will create a folder. Let's say that conf here go mod okay you see there is only one file here go mode. Let's open this one by using Golang I am using goal end for my projects file. Open presentations. This one let me open. Okay it is already in presentation mode. So here when you open Gomot file, you will see there is only module information plus there is a version information. I will start creating a main file. Main in this file, this is Golang by default. Adds this package, the folder name as a package in this file. But I will change this one as main because I want this package to be executable. Funk main. You see this main is a special function. You can run it. Let's do our famous stuff. Print run hello world. Okay. When you run it, you will see it is in the output. Cool. Let's start with the variable declarations. But I will create a separate directory for this variables and a separate profile variables in this file let's define a function. Let's say that run in this run function we can define our variables arcount. Let's say that this will be an integer and the value will be 34. Just print this one. You see, it complains about you defined it, but you have not used it count. Okay, so let's try to run this one from main functions. Variables run. You see, this import is automatically added to this resource file. Hello world 34. Let's continue to define a couple of variables. Here the inline one limit is equal to ten. What else we can define the slice numbers is equal to square bracket, two, five, seven, what else? We can define a limited slice here it you can define this length in advance. Let's say that this is two, this is limit, this is numbers, and here let me do something. The first value will be this one. Duplicate it. Let's try to compile this or run this. Let's see what happens. It okay, I did something wrong. One, two, you see index out of range, two, because you define the limit two, but you are trying to add the third item, right? I will delete this one to make it work. So if you do not add for example, second value, then you will see the value will be filled by the default values, which is zero is the default value of the integer type. What else we can define students map in this case, I am saying that the student id and the grade lot 64 here, student id is one, the value is this one, and student Id is two, and value is 100% here. And just print students. This is wrong. It all right, let's write this function. Run this function again, and as you can see it is correctly working. What about functions? Let's switch to functions. Here I define another directory functions. Just create another resource file functions. Here I define some function. It takes a and b as integer and returns integer. You see, you don't need to define integer for all of the types if they are repetitive. You define your variable names and integer. I think this is valid for typescript also. You return a plus b. Right, let's do another one. Funk. This time it will be multiply, multiply ab. They are integer return integer return ab. So here, in this case, one function starts with capital letter, another starts with lowercase letter. Here, let's go to main function. Just comment this one functions sum. But what about you see, there is no multiply. Why? Because it is private. That is the commission inside codelack. Okay, inside some function, just provide 45, 55 and wrap it with here. Hello world. The values 100. This is it for functions. What about testing? In my functions package I am creating a file which is called functions test. Okay, you see, the icon is changed for best in Golang. In order to write a test, you can start with test keyword and it will automatically suggest you to sum. So I am testing sum result is equal to sum two three. Here, if result is not equal to five, then T-R-F wanted five cut result. Let's run this one. So basically we are using t reference in order to verify something. But let's say that you change this function to something like this. Then when you go back to function and run it, you will see one five but got six. So when you change production code by doing this, you may understand. Okay, there is a problem. Let's delete this one. Okay, what about test tables funk this time let's say that test sum in fetching t here I will define a struct, something like you define a JSON inside Javascript or typescript, or you define a map in any kind of language. So inside the struct you can define your variables and types, something like this. This is slice of struct. So let's say that you haven't defined any kind of object, you don't have an object, but you can define something like this. This will be the input, let's say that integer and the expected output. So this is a table. Now I can put my values inside it. Okay, this will be a a. There will be a b. Unexpected. So if you provide two and three to the function, you need to get five. What else? If you provide this one and this one, it will be. Let's put some wrong values. For example 100 200, it will be 400. Okay, this one's then in order to run it, four. I'm not interested in the index, I'm only interested in parameter range parameters. Let's call the sum function and provide parameter a. Parameter b. Then parameter not parameters, parameter b. Assign this one to a value. Okay, sum is cool. If sum is not equal to parameter expected, then you can say t error f wanted something, got something so invanted part parameter expected. Another one is sum. So let's execute this function and see what is going on. You see, wanted 400 but got 300. You see, that means this shouldn't be 400, this should be 300. Another one wanted five but got seven. You see, this is seven. Just execute this one. But normally you don't change test code most of the time. So you change test, but right after change production code. Okay, this is test. What about coverage? You can just select this one and run with coverage. You can say that, or you can do this. Just open terminal in terminal go. Best cover this one. So you see the coverage of the functions is 50%. There is no coverage in arrivals part in functions because there is also multiply function. But I cannot test it right now. And what about this coverage alt file? Let's test. Yeah, you see, go to cover. I just wanted to see HTML output of this one. When you do that, you will see the HTML output. I cannot show it right now but let's continue with the column part. What can we do next? Yes, so we can talk about building artifacts right here. Let's try to build an artifact. Go build. In my case this will be, let's say the conf 42. When you do a build operation, you will see binary will be generated. Something like this. And when you execute it, you will see the same output. Very simple. What about using this one in the containerization? Generating a Docker image let's create a docker image for this docker file here in docker file I will start from calling as builder. Okay. This is my first stage and I will do run. I will create a folder first and change my work directory to this one. Then I will copy everything from my project folder to docker context. I will download all the dependencies if I have any. Then I will generate my binary. So this will generate a binary. Then in the second stage I will use scratch image. Then I will copy from builder. So from the first stage in this path I will copy from the builder at this page to mypad. Let's say that bin app and just put this one to entry point as bin app. Let's try to build this one. Docker build ht let's wait for this. It will download the Golang docker image and use it. Build a docker image and then generate something. Let's see Docker images. You see we have conf fourty two and the size is only 1. When I run comfort I got exactly same output from this part. So that was all for this session. Thanks for listening the theoretical information and watching for my showcase about the calling usage. Hope it was a very useful session for you. Maybe see you in the next sessions.
...

Huseyin Babal

Software Development Team Lead @ Hazelcast

Huseyin Babal's LinkedIn account Huseyin Babal's twitter account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways