Bonjour Ă tous!
Je m'appelle Lex et je suis l'hĂŽte de la chaĂźne
YouTube "
IT Beard ". Et je suis un associé de 6 ans. Récemment, j'avais envie d'aller au-delà de ma technologie de base (C # /. NET), et de comprendre l'essence du
paradoxe Blob . J'ai fermement décidé de m'essayer dans une autre langue, et le choix s'est fait par hasard sur Go.
Afin d'acquérir des connaissances de maniÚre structurée, je me suis inscrit à un cours de mail.ru, que vous pouvez trouver ici:
https://www.coursera.org/learn/golang-webservices-1 . En fait, ce que j'ai appris de la premiÚre semaine de formation dans ce cours sera discuté plus loin. C'est parti!
Je vais commencer par une petite intro sur la langue.
Go Ă©tait dĂ©jĂ dĂ©veloppĂ© Ă l'Ă©poque des processeurs multicĆurs (2007-2009), donc tout est trĂšs bien ici avec la parallĂ©lisation du travail sur les cĆurs. De plus, la langue fonctionne trĂšs bien avec les demandes concurrentielles (simultanĂ©es). En gĂ©nĂ©ral, une recherche pour toutes sortes de services Web et de systĂšmes Web chargĂ©s. Exactement ce dont j'ai besoin, car j'ai dĂ©veloppĂ© des API Web (API Web) ces derniĂšres annĂ©es.
Commencer
Pour travailler avec la langue, il suffit d'installer
le progiciel «Go tools» de 118 Mo et vous pouvez commencer à coder.
Les scripts ont l'
extension * .go et sont exécutés par la commande
go sur la ligne de commande (je suis un adhérent de la ligne de commande Windows). La commande
gofmt place tous les espaces d'indentation et crée des bonbons à partir du fichier (embellisseur de code hors de la boßte). Comme dans mon sous-réseau préféré, dans Go, l'exécution du programme commence par la méthode
principale .
Une fonctionnalité intéressante a immédiatement attiré mon attention -
vous ne pouvez pas mettre de point-virgule Ă la fin de la ligne :)
Go est un autre langage (avec python, c #, php, js, ts et autres), qui est pratique pour travailler avec VSCode.
VSCode lui-mĂȘme fournit absolument tous les packages et dĂ©pendances nĂ©cessaires lors de l'Ă©criture du code. Lors de l'enregistrement de l'IDE, veuillez exĂ©cuter gofmt pour vous et rendre le code encore plus beau.
Variables
Tout est familier ici: il existe de nombreux types différents, il existe des valeurs par défaut. D'inhabituel pour un donateur, le mot-clé
var signifie que la variable ira plus loin, et le type de la variable peut ĂȘtre dĂ©clarĂ© ou pas dĂ©jĂ aprĂšs le nom de la variable. Exceptionnellement.
En gĂ©nĂ©ral, il existe de nombreuses façons de dĂ©clarer et d'initialiser des variables. Vous pouvez mĂȘme affecter des valeurs Ă plusieurs variables, sĂ©parĂ©es par des virgules, sur la mĂȘme ligne. Et en passant, il n'y a pas de transtypages implicites.
Et Go a également un opérateur "
: = ", qui vous permet de déclarer et d'initialiser immédiatement de nouvelles variables (et presque toujours uniquement de nouvelles). Salut Pascal;)
Vue d'enregistrement:
perem1, perem2 := 2, 3
soit crée deux nouvelles variables, soit en crée une, et la seconde affecte simplement une nouvelle valeur. Cela signifie que si les deux variables existent déjà , cela ne fonctionnera pas et vous obtiendrez une erreur, disent-ils utiliser l'affectation habituelle. Opérateur
: = doit créer quelque chose :)
Il y a aussi un faux drÎle - le caractÚre de soulignement "_". Cela signifie l'absence d'une variable, quelque chose comme ça :)
(dans les objets tranchants, comme il s'est avéré, c'est aussi: https://docs.microsoft.com/en-us/dotnet/csharp/discards )
Moment amusant avec des chaßnes: le décompte standard de la longueur de chaßne d'une chaßne
len (str) compte les
octets , et en UTF8 un caractÚre peut peser plus. Pour compter les caractÚres appelés
runes , vous devez utiliser la
méthode utf8.RuneCountInString (str) du package «utf8». Et, et pourtant - nous ne changeons pas les lignes (comme dans votre préféré).
Constantes
Les constantes peuvent ĂȘtre dĂ©clarĂ©es par lots. Les constantes ont un type intĂ©ressant, ou quelque chose comme ça -
iota . Je l'appellerai Jopta. Jopta vous permet de faire certaines constantes sur la base d'autres, quelque chose comme un itérateur pour les constantes (quelque chose qui rappelle le
rendement d'un sous-réseau).
Et pourtant, les constantes ne peuvent pas ĂȘtre saisies. Pour de telles constantes, le compilateur dĂ©cide de quel type elles sont au bon moment. IdĂ©alement, ce qui est dĂ©jĂ lĂ .

Pointeurs
Oui oui Il y a des indications ici, mais cela ne semble pas trÚs effrayant. Ils disent qu'ils ne sont pas numérotés, et vous ne pouvez pas obtenir le prochain pointeur en ajoutant un pair au pointeur. Ici, c'est un peu comme une variable qui stocke un lien vers une autre variable (jusqu'à présent, je l'ai en quelque sorte compris).
Le pointeur est spécifié via un esperant ou la
nouvelle méthode
(type) (pour obtenir un pointeur vers un type, pas une variable):

Si vous accédez directement au pointeur, le lien change. Et si par l'opérateur "
* ", alors la valeur de la variable qui se trouve derriÚre le pointeur (vers lequel il pointe) change. En général, ce n'est pas encore trÚs clair, mais alors, disent-ils, ce sera plus clair.
Tableaux
La taille du tableau fait partie du type de données! Ainsi, les tableaux de différentes dimensions sont en fait différents types de données et ne sont pas compatibles.

Mais que faut-il pour les tableaux s'ils sont si secs et immuables (ils ne peuvent pas ĂȘtre modifiĂ©s pendant l'exĂ©cution). Par consĂ©quent, nous avons proposĂ© de telles
tranches (tranches) basées sur des tableaux.

Une tranche a une
longueur et une
capacité . Cela m'a rappelé un peu le
type de données
nvarchar de SQL. C'est-à -dire vous pouvez allouer de l'espace mémoire (allocation de mémoire) à vos baies, mais y mettre des baies de n'importe quelle longueur (jusqu'à la capacité). Bref, la chose est intéressante, il faut s'y habituer. Pour une utilisation pratique des tranches, il existe toutes sortes de méthodes telles que
make (), append (), len (), cap () et, bien sûr, d'autres. à partir d'une tranche (tranche), vous pouvez obtenir légÚrement une sous-tranche (tranche de tranche). Et en passant,
append () étend la capacité de la tranche.
Si la sous-tranche est égale à la tranche, alors en fait, ils se réfÚreront à un morceau de mémoire. Et en conséquence, un changement de la valeur dans une tranche entraßnera un changement dans la deuxiÚme tranche. Mais si l'un d'eux est développé via
append () , un nouveau morceau de mémoire sera alloué.
Bref, tout est sérieux avec la mémoire :)
Carte, table de hachage, tableau associatif
Tout cela est le mĂȘme. Allez sur des tables de hachage pour des recherches de clĂ©s rapides. InitialisĂ© comme suit:

Vous pouvez créer des sous-tables (Map Map), etc. (n'importe quel niveau d'imbrication, un peu comme). Il existe une valeur par défaut qui renvoie des clés inexistantes. Il est tiré du type de clé (pour bool, puis false). Pour savoir si une variable est retournée par défaut, c'est-à -dire que la clé est manquante - utilisez la clé pour l'existence de la clé (chose intéressante):

Structures de contrĂŽle
Il y a un if-else. Un peu plus intéressant que dans les objets tranchants, car vous pouvez utiliser les conditions d'initialisation pour if.
Il y a un swith-case. Les pauses n'ont pas besoin d'ĂȘtre dĂ©finies, et c'est une diffĂ©rence. Inversion de la logique) Si vous souhaitez Ă©galement vĂ©rifier la condition suivante, vous devez Ă©crire
fallthrough .
Il y a pour. Et tout cela avec des cycles.

Avec tranche itérative plus ludique (opérateur de plage):

Et mĂȘme par carte de hachage, vous pouvez itĂ©rer (bien que la sĂ©quence soit souvent diffĂ©rente, car la carte n'est pas directionnelle):

Pour le type,
la plage de chaĂźnes itĂšre sur les runes, pas sur les octets.
Les fonctions
Déclaré via le mot clé
func . De plus, l'inversion de la logique est à nouveau comparée au sous-réseau - les paramÚtres d'entrée sont indiqués en premier, puis le type de la valeur de retour (vous pouvez immédiatement le nommer).
Les fonctions peuvent renvoyer
plusieurs résultats , tout comme les
tuples dans un sous - réseau .
Les valeurs nommées renvoyées par la fonction sont initialisées par défaut avec des valeurs par défaut pour le type.
Et pourtant, vous pouvez créer
des fonctions variables qui ont un nombre illimitĂ© de paramĂštres d'entrĂ©e du mĂȘme type (comme param dans le sous-rĂ©seau). Et puis un type spĂ©cifique de tranche vient Ă l'entrĂ©e de la fonction.
Les fonctions peuvent avoir des noms ou ĂȘtre sans nom -
anonymes . Et ils peuvent ĂȘtre appelĂ©s, peuvent ĂȘtre affectĂ©s Ă des variables. Cela ressemble Ă JavaScript. Vous pouvez mĂȘme crĂ©er des types basĂ©s sur des fonctions! Les fonctions peuvent ĂȘtre passĂ©es comme paramĂštres (lire les dĂ©lĂ©guĂ©s du sous-rĂ©seau)
Il y a mĂȘme une
fermeture (uuuh, effrayante)! Vous pouvez atteindre les variables de la fonction en dehors de celle-ci (lire, dans la fonction parent). Ce sont les tartes.
Vous pouvez déclarer l'
exécution différée des fonctions . Grùce au mot clé
defer, cela se fait. C'est-à -dire les fonctions différées sont exécutées à la fin de la fonction dans laquelle elles sont déclarées, dans l'ordre inverse de la déclaration de ces fonctions différées. Ici. De plus, l'initialisation des arguments des fonctions différées se produit lorsque le bloc de
report est
déclaré . C'est important, surtout si une autre fonction est prise comme argument - elle sera exécutée beaucoup plus tÎt que prévu!
PANIQUE! Go a une telle fonction -
panic () . Câest comme la
remise en jeu, mais pire. Cette fonction arrĂȘte l'exĂ©cution du programme. Mais cette mĂȘme panique peut ĂȘtre traitĂ©e par report, car elle est exĂ©cutĂ©e de n'importe quelle façon Ă la fin de la fonction, mĂȘme aprĂšs une panique. Et pourtant - panique, ce n'est pas un essai. C'est pire!
Structures (quasi-objets)
Le go n'est pas tout Ă fait un langage de paradigme OOP. Mais il y a des choses comme les
structures . Si vous ĂȘtes du monde du sous-rĂ©seau, vous savez que nous avons Ă©galement des structures - ce sont des mappages d'objets qui peuvent ĂȘtre stockĂ©s sur la pile (types de valeurs). Dans Go, la structure est en quelque sorte le seul moyen de faire quelque chose comme un objet. Je ne peux pas encore parler des types de valeur, mais la nature de l'interaction avec les structures est trĂšs similaire Ă celle dĂ©taillĂ©e.
Chaque structure est essentiellement un type distinct et peut avoir un ensemble de propriétés de types spécifiques (y compris le type d'une autre structure ou type de fonction):

De plus, un certain mécanisme d'héritage direct des objets du sous-réseau est vu ici. Dans l'image ci-dessus, la structure de
compte est imbriquée avec la structure de
personne . Cela signifie que tous les champs de
Personne seront disponibles dans une variable de type
Compte . Si les noms de propriété coïncident (dans l'exemple ci-dessus
Id, Name ), il n'y aura pas de conflit, mais la valeur d'un champ supérieur sera prise:

Les méthodes
Oui, il n'y a pas seulement la similitude des objets, mais aussi des méthodes. Presque OOP :) Une méthode est une
fonction liée à un type spécifique (par exemple, à une structure). Une méthode diffÚre d'une fonction dans une déclaration: aprÚs le mot clé
func , entre parenthÚses, vous devez spécifier le type auquel appartient cette méthode et le rÎle de passer une variable de ce type. Quel est le rÎle? Si vous mettez un astérisque devant le type, la variable sera transmise par référence (rappelez-vous les pointeurs, elle était là aussi), et en conséquence, à l'intérieur de la méthode, nous travaillerons avec un type spécifique, et non une copie de celui-ci.

D'aprĂšs l'image ci-dessus, nous pouvons conclure que
UpdateName n'a pas de sens, car il modifie la copie de la structure et non l'original. Et cette copie ne revient pas. Alors que
SetName va changer la structure d'origine (grùce à l'astérisque et en passant par référence).
Les méthodes dans les structures
sont héritées (et selon les rÚgles d'héritage de propriété), c'est-à -dire la structure parente a accÚs à toutes les méthodes imbriquées dans ses structures.
D'autres types peuvent avoir des mĂ©thodes, pas seulement des structures. Cela peut ressembler Ă des mĂ©thodes d'extension de sous-rĂ©seau, mais non. Les mĂ©thodes dans Go ne peuvent ĂȘtre créées que pour les types locaux, c'est-Ă -dire types qui sont dĂ©clarĂ©s dans ce package (Ă propos des packages un peu plus loin).
Packages, portée, espaces de noms
Je viens de rĂ©aliser que Go n'a pas NEIMSPACE! GĂ©nĂ©ralement! Je m'en suis rendu compte quand, aprĂšs la compilation, une erreur est sortie, ils disent que dans un dossier j'ai deux fichiers avec la mĂ©thode principale. Il s'avĂšre qu'au stade de la compilation, tout, depuis papa, semble ĂȘtre collĂ© ensemble dans une seule toile! Un dossier est en fait un espace de noms. C'est tellement magique, camarades :)
Voici, en passant, ce que dit le dock:

Remarque pour vous-mĂȘme:
fumez un quaiEt voici un autre petit article dans le sujet:
https://www.callicoder.com/golang-packages/#the-main-package-and-main-functionAinsi, disent-ils, la structure de dossier de base ressemble Ă :

bin - binaires compilés
pkg - fichiers d'objets temporaires
src - sources
Les packages font référence au nom du dossier dans lequel se trouvent les fichiers de packages. Oui, un package peut contenir de nombreux fichiers importés les uns dans les autres.
Autre rÚgle intéressante: les fonctions, propriétés, variables et constantes commençant par une majuscule
peuvent ĂȘtre utilisĂ©es en dehors du package , c'est-Ă -dire
ĂȘtre importĂ© . Tout avec une petite lettre est utilisĂ© uniquement Ă l'intĂ©rieur du colis. Un analogue
des modificateurs d'accÚs du sous-réseau.
Le mot-clé d'
importation fonctionne dans un fichier, pas dans un package.
Interfaces
Les interfaces ici sont intĂ©ressantes. Nous n'avons pas besoin d'hĂ©riter des interfaces de nos structures. Il suffit que la structure, qui vient comme paramĂštre d'entrĂ©e d'une certaine mĂ©thode qui prend un type d'interface, implĂ©mente les mĂ©thodes de cette interface. Et il n'y a aucun problĂšme. C'est-Ă -dire les mĂ©thodes d'interface ne doivent pas nĂ©cessairement ĂȘtre implĂ©mentĂ©es par la structure. Mais la structure doit contenir l'implĂ©mentation de toutes les mĂ©thodes requises dans une fonction particuliĂšre, oĂč le type d'interface est utilisĂ© comme paramĂštre d'entrĂ©e.
Il s'avÚre que, contrairement à Go, l'interface est une caractéristique de la fonction dans laquelle elle est utilisée, et non une caractéristique d'une structure spécifique (objet).
Si c'est encore plus simple, alors la logique est la suivante: vous n'avez pas besoin d'ĂȘtre capable de charlatan pour ĂȘtre un canard. Si vous savez charlatan, alors vous ĂȘtes probablement un canard :)
Et au fait, si votre structure implémente toutes les méthodes d'une interface, alors cette structure
peut ĂȘtre affectĂ©e comme valeurs de la variable de l'interface implĂ©mentĂ©e . Quelque chose comme ça :)
Type boĂźtier de commutateur
Go a un boßtier de commutation spécial qui peut fonctionner en fonction du type entrant. Chose cool:

Soit dit en passant, voici comment vous pouvez
convertir un type en un autre (par exemple, un type d'interface en un type de structure afin d'obtenir des champs de structure qui ne sont pas accessibles depuis l'interface):
ok - signe booléen que la conversion a réussi. Nous avons déjà rencontré les signes :)
L'interface vide est la bĂȘte du monde de Go. Cela peut prendre n'importe quel type. Quelque chose comme
dynamique ou
Object in. Par exemple, il est utilisé dans
fmt.Println () et des fonctions similaires qui utilisent une interface vide dans l'implémentation.
Les interfaces peuvent ĂȘtre intĂ©grĂ©es les unes aux autres, et ainsi faire la composition des interfaces (ce qui est dit dans la lettre
I (ségrégation des interfaces) des principes
SOLID )
Les tests
Dans Go, toutes les fonctions de test commencent par le mot
Test et l'entrée du test du module de
test est acceptée. Les fichiers sont nommés par le nom du fichier de test + mot _test (
main_test.go - teste le fichier
main.go ). De plus, les tests et les fichiers de test sont dans un seul paquet!

Ăpilogue
Câest tout! Merci de votre attention et je suis prĂȘt Ă discuter des problĂšmes dans les commentaires. Je vous retrouve dans les notes suivantes de mes cours!
PS Vous pouvez regarder toutes mes promenades de code sur cette semaine de formation sur
github