Hello!
My name is Lex and I am the leader of the "
ITB " youtube channel. And I’m an experienced worker with 6 years experience. Recently, I had a desire to go beyond my core technology (C # /. NET), and to
get to know the essence of
the Blub paradox . I firmly decided that I would try myself in another language, and the choice by chance fell on Go.
In order to get knowledge structured, I enrolled in a course from mail.ru, which you can find here:
https://www.coursera.org/learn/golang-webservices-1 . Actually about what I learned from the first week of training in this course, further and will be discussed. Let's go!
')
I'll start with a little intro for the language.
Go was developed in the days of multi-core processors (2007-2009), so with parallelization of work on the cores everything is very good here. In addition, the language works fine with competitive (simultaneous) requests. In general, a godsend for all sorts of web services and loaded web systems. Just what you need for me, for the last years I have been developing web eipia (Web API).
Start
To work with the language, it is enough to install the
software package “Go tools” with the size of 118mb, and you can start coding.
The scripts have the
* .go extension and are run by the
go command on the command line (I am an adherent of the windows command line). The
gofmt command arranges all spaces and makes the file candy (code beautifier out of the box). As in my favorite dot, in Go, the execution of a program begins with the
main method.
Immediately struck a cool feature -
you can not put a semicolon at the end of the line :)
Go is another language (along with python, c #, php, js, ts and others), which is convenient to work with in VSCode.
VSCode itself delivers absolutely all the necessary packages and dependencies in the course of writing code. When you save the IDE, it kindly launches gofmt for you and makes the code even more beautiful.
Variables
Everything is familiar here: there are many different types, there are default values. Of the unusual for a dongle, the
var keyword indicates what the variable will go next, and the type of the variable can be declared or not by the name of the variable. Unusually.
In general, there are many ways to declare and initialize variables. You can even assign values to several variables separated by a comma in one line. And by the way, there are no implicit ghosts.
And in Go there is a "
: = " operator that allows you to declare and immediately initialize new (and almost always only new) variables. Hello Pascal;)
Record type:
perem1, perem2 := 2, 3
either creates two new variables, or creates one of them, and the second simply assigns a new value. This is me to the fact that if both variables already exist, then this does not work and you get an error, they say, use the usual assignment. Operator
: = must create something :)
And then there is a funny fake - the underscore "_". It indicates the absence of a variable, something like this :)
(in sharps, as it turned out, it also exists: https://docs.microsoft.com/en-us/dotnet/csharp/discards )
A funny moment with strings: the standard length string count
len (str) counts
bytes , and in UTF8, the character can weigh more. To count the characters, called
runes , you need to use the method
utf8.RuneCountInString (str) from the package "utf8". And, and more - the lines are not changed (just like in your favorite dotnet).
Constants
Constants can be declared bundles. Constants have an interesting either type or something -
iota . I will call it Yopta. Yopta allows you to make some constants based on others, something like an iterator for constants (something reminded of the
yield from the dotnet).
And yet, constants may not be typed. For such constants, the compiler itself decides what type they are at the right moment. Conveniently, what is there.

Pointers
Yes Yes! There are pointers. But it seems not very scary. It is said that they are not numbered, and it is impossible to add to the index of the even one, get the next pointer. Here it seems to be a variable that stores a reference to another variable (as long as I understand it somehow).
A pointer is specified via an ampersant or the
new (type) method (to get a pointer to a type, not a variable):

If you refer directly to the pointer, the link changes. And if through the operator "
* ", then the value of the variable that lies behind the pointer (to which it points) changes. In general, it is not very clear, but then, they say, it will be clearer.
Arrays
The size of the array is part of the data type! So, arrays of different dimensions are in fact different data types and are not compatible.

But nafig need arrays, if they are so dry and unchangeable (they can not be changed in runtime). Therefore, they invented such
slices (slices) based on arrays.

The slice has a
length (length) and a
capacity (capacity) . It reminded me a bit of the
nvarchar data type from SQL. Those. You can allocate space in memory (memory allocation) for your arrays, but put arrays of any length (up to capacity) there. In short, an interesting thing, you need to get used to it. For convenient use of slices, there are all sorts of methods like
make (), append (), len (), cap () and, for sure, others. From one slice (slice) you can slightly get a cut (slice slice). And by the way,
append () expands the capacity of a slice.
If the sub-cut is equal to the slice, then in fact they will refer to one memory location. And accordingly, a change in the value in one slice will lead to a change in the second slice. But if one of them is expanded via
append () , then a new memory will be allocated.
In short, with the memory here everything is serious :)
Map, hash table, associative array
All this one and the same. Go has hash tables for quick key searches. Initialized as follows:

You can make subtables (mapy map), etc. (any level of nesting, sort of like). There is a default value that is returned for non-existent keys. It is taken from the key type (for bool, it is false). To know if the variable returned by default, i.e. that the key is missing - use the sign of the existence of the key (interesting thing):

Control structures
There is an if-else. Slightly more interesting than with sharps, because you can use initialization conditions for if.
There is a swith-case. Breaks do not need to put, and this is the difference. Inversion of logic) If necessary, so that the following condition is also checked - you need to write
fallthrough .
There are for. And all with cycles.

Iterating over slices is more fun (range operator):

And even the hash map can be iterated (although the sequence will often be different, because the map is not directed):

For
string type, it iterates over runes, not bytes.
Functions
Declared through the
func keyword. And again, the inversion of logic compared to the dotnet - first enter the input parameters, and then the type of the return value (you can immediately named).
Functions can return
multiple results , just like the
tuples in a datnet .
Named values returned by a function are, by default, initialized with values by default for the type.
And also, you can make
variable functions that have an unlimited number of similar input parameters (like param in data). And then a specific type slice comes to the input of the function.
Functions can have names, and can be and without names -
anonymous . And they can be called, can be assigned to variables. It looks like javascript. You can even make types based on functions! Functions can be passed as parameters (read delegates from datnet)
There is even a
closure (hell, awful)! You can reach the variables outside the function from the function (read, in the parent function). These are the pies.
You can declare a
deferred execution of functions . Through the
defer keyword this is done. Those. deferred functions are executed at the end of the function in which they are declared, in the reverse order of declaring these deferred functions. Here it is. Moreover, the initialization of the deferred function arguments occurs when the
defer block is
declared . This is important, especially if there is another function as an argument - it will be executed much earlier than you expect!
PANIC! Go has this function -
panic () . It's like
throwing in dotnet, but worse. This function stops the execution of the program. But this same panic can be handled by defer, as it is executed anyway at the end of the function, even after panic. And more - a panic, it is not try-catch. This is worse!
Structures (near-objects)
It is said that Go is not exactly an OOP-paradigm language. But there are such things as
structures . If you are from the world of datnet, then you know that we also have structures - these are displays of objects that can be stored on the stack (types of values). In Go, a structure is like the only way to do something like an object. I can’t talk about value types yet, but the nature of interaction with structures is very similar to that of.
Each structure is essentially a separate type and can have a set of properties of specific types (including the type of another structure or type of function):

In addition, there is some mechanism of direct object inheritance from the data point. In the picture above, the
Account structure is nested with the
Person structure. This means that all the fields from
Person will be available in a variable of type
Account . If the property names coincide (in the example above,
Id, Name ) there will be no conflict, but the value of the higher field will be taken:

Methods
Yes, there is not only the similarity of objects, but also methods. Almost OOP :) A method is a
function tied to a specific type (for example, to a structure). The method differs slightly from the function by declaring: after the
func keyword in parentheses, you need to specify the type to which this method belongs, and the role of passing a variable of this type. What is the role? If you put an asterisk in front of the type, then the variable will be passed by reference (we remember the pointers, it was there as well), and as a result, inside the method we will work with a specific type, not its copy.

From the picture above, we can conclude that
UpdateName does not make sense, because it changes the copy of the structure, not the original. And this copy does not return. While
SetName will change the original structure (thanks to the asterisk and transmission by reference).
Methods in structures
are inherited (and according to the rules for inheriting properties), i.e. parent structure has access to all methods nested in its structures.
Methods can be in other types, not only in structures. It may seem that this is similar to the extension methods from dotnet, but no. Methods in Go can only be created for local types, i.e. types that are declared in this package (about packages a little further).
Packages, scope, namespaces
Only now I realized that there are no NEIMSPEYS in Go! At all! I realized this when, after compilation, I got an error, saying that in the same folder I have two files with the main method. It turns out that at the compilation stage everything from daddy seems to be glued together in one canvas! The folder is in fact the namespace. Such magic, comrades :)
Here, by the way, what is said in the dock:

A note for yourself:
to smoke a dockAnd here's another little article on the topic:
https://www.callicoder.com/golang-packages/#the-main-package-and-main-functionSo, they say, the basic folder structure looks like:

bin - collected binaries
pkg - temporary object files
src sources
Packages name the name of the folder in which the package files are located. Yes, a package can have many files that are imported into each other.
Another interesting rule: functions, properties, variables and constants starting with a capital letter
can be used outside the package , i.e.
imported . Anything with a small letter is used only inside the package. Analogue
of access modifiers from datnet.
The
import keyword works within a file, not a package.
Interfaces
With interfaces here things are interesting. We do not need to inherit interfaces with our structures. It is enough that the structure that comes as an input parameter to a certain method that accepts an interface type implements the methods of this interface. And there are no problems. Those. interface methods need not be implemented by a structure. But the structure must contain the implementation of all methods that are required in a particular function, where the interface type is used as an input parameter.
It turns out that, in contrast to a datnet, in Go an interface is a characteristic of the function in which it is used, and not a characteristic of a specific structure (object).
If it is even simpler, then the logic is this: no need to be able to quack to be a duck. If you are able to quack - then most likely you are a duck :)
And by the way, if your structure implements all the methods of an interface, then this structure
can be assigned as values of a variable of the implemented interface . Something like this :)
Type Switch-Case
In Go, there is a special switch-case that can work depending on the incoming type. Cool stuff:

By the way, this is how you can
convert one type to another (for example, an interface type to a structure type, to get structure fields that are not accessible from the interface):
ok - a boolean indicates that the conversion was successful. Signs we have already encountered :)
The blank interface is the beast in the Go world. It can take any type at all. Something like
dynamic or
Object in datnet. For example, it is used in
fmt.Println () and similar functions that use an empty interface in the implementation.
Interfaces can be built into each other, and thus make the composition of interfaces (what is said in the letter
I (interface segregation) of the principles of
SOLID )
Tests
In Go, all functions of tests begin with the word
Test , and the test testing module parameter is taken as input. Files are named after the file being tested + the word _test (
main_test.go - tests for the
main.go file). And the tests and test files are in the same package!

Epilogue
That's all! Thank you for your attention, and ready to discuss questions in the comments. See you in the following notes from my classes!
PS All my code walks for this week of training you can look at
github