Articles

Go (langage de programmation)

Posted by admin

Go est influencé par C, mais en mettant l’accent sur une plus grande simplicité et sécurité. Le langage se compose de:

  • une syntaxe et un environnement adoptant des modèles plus courants dans les langages dynamiques:
    • optional concise variable declaration and initialization through type inference (x := 0au lieu de int x = 0;or var x = 0;).
    • Rapide de la compilation.
    • Gestion des paquets distants (go get) et documentation des paquets en ligne.,
  • approches distinctives de problèmes particuliers:
    • primitives de concurrence intégrées: processus légers (goroutines), canaux et instructionselect.
    • Un système d’interface à la place de l’héritage virtuel, et type embedding au lieu de l’héritage non virtuel.
    • une chaîne d’outils qui, par défaut, produit des binaires natifs liés statiquement sans dépendances externes.,
  • Un désir de garder la spécification du langage assez simple pour tenir dans la tête d’un programmeur, en partie en omettant des fonctionnalités communes dans des langages similaires.

SyntaxEdit

la syntaxe de Go inclut des modifications de C visant à garder le code concis et lisible. Un opérateur de déclaration/initialisation combiné a été introduit qui permet au programmeur d’écrire i := 3 ou s := "Hello, world!", sans spécifier les types de variables utilisées. Cela contraste avec C int i = 3; et const char *s = "Hello, world!";., Les points-virgules terminent toujours les instructions, mais sont implicites lorsque la fin d’une ligne se produit. Les méthodes peuvent renvoyer plusieurs valeurs, et renvoyer une paire result, err est la manière conventionnelle dont une méthode indique une erreur à son appelant dans Go. Go ajoute des syntaxes littérales pour initialiser les paramètres de structure par nom et pour initialiser les cartes et les tranches. Comme alternative à la boucle à trois instructions for de C, Les expressions range de Go permettent une itération concise sur des tableaux, des tranches, des chaînes, des cartes et des canaux.,

TypesEdit

pour chaque type T et chaque constante entière non négative n, Il existe un type de tableau noté T; les tableaux de longueurs différentes sont donc de types différents. Les tableaux dynamiques sont disponibles sous forme de » tranches », notées T pour certains types T. ceux-ci ont une longueur et une capacité spécifiant quand une nouvelle mémoire doit être allouée pour étendre le tableau. Plusieurs tranches peuvent partager leur mémoire sous-jacente.

Les pointeurs sont disponibles pour tous les types, et le type pointeur vers T est noté *T., La prise d’adresse et l’indirection utilisent les opérateurs& et*, comme en C, ou se produisent implicitement via l’appel de méthode ou la syntaxe d’accès aux attributs. Il n’y a pas d’arithmétique de pointeur, sauf via le spécial dangereux.Type de pointeur dans la bibliothèque standard.

pour une paire de types K, V, le type mapV est le type des tables de hachage mappant les clés de type K aux valeurs de type V. Les tables de hachage sont intégrées dans le langage, avec une syntaxe spéciale et des fonctions intégrées. chan T est un canal qui permet d’envoyer des valeurs de type T entre des processus Go simultanés.,

En dehors de sa prise en charge des interfaces, le système de type de Go est nominal: le mot-clé type peut être utilisé pour définir un nouveau type nommé, qui est distinct des autres types nommés qui ont la même disposition (dans le cas d’une structure, les mêmes membres dans le même ordre). Certaines conversions entre types (par exemple, entre les différents types entiers) sont prédéfinies et l’ajout d’un nouveau type peut définir des conversions supplémentaires, mais les conversions entre types nommés doivent toujours être invoquées explicitement., Par exemple, le mot-clé type peut être utilisé pour définir un type pour les adresses IPv4, basé sur des entiers non signés 32 bits:

type ipv4addr uint32

Avec cette définition de type, ipv4addr(x) interprète la valeur uint32 x comme une adresse IP. Assigner simplement x à une variable de type ipv4addr est une erreur de type.

Les expressions constantes peuvent être typées ou « non typées »; elles reçoivent un type lorsqu’elles sont affectées à une variable typée si la valeur qu’elles représentent passe une vérification au moment de la compilation.,

Les types de fonctions sont indiqués par le mot-clé func; ils prennent zéro ou plusieurs paramètres et renvoient zéro ou plusieurs valeurs, qui sont toutes tapées. Les valeurs de paramètre et de retour déterminent un type de fonction; ainsi, func (string, int32) (int, error) est le type de fonctions qui prennent une chaîne et un entier signé de 32 bits, et renvoient un entier signé (de largeur par défaut) et une valeur de l’erreur de type d’interface intégrée.

tout type nommé a un ensemble de méthodes qui lui est associé., L’exemple D’adresse IP ci-dessus peut être étendu avec une méthode pour vérifier si sa valeur est une norme connue:

// ZeroBroadcast reports whether addr is 255.255.255.255.func (addr ipv4addr) ZeroBroadcast() bool { return addr == 0xFFFFFFFF}

En raison du typage nominal, cette définition de méthode ajoute une méthode à ipv4addr, mais pas sur uint32. Bien que les méthodes aient une définition spéciale et une syntaxe d’appel, il n’y a pas de type de méthode distinct.

interface systemEdit

Go fournit deux fonctionnalités qui remplacent l’héritage de classe.

le premier est l’intégration, qui peut être considérée comme une forme automatisée de composition ou de délégation.,: 255

Les seconds sont ses interfaces, qui fournissent un polymorphisme d’exécution.: 266 les Interfaces sont une classe de types et fournissent une forme limitée de typage structurel dans le système de type nominal de Go. Un objet qui est d’un type d’interface est également d’un autre type, tout comme les objets C++ étant simultanément d’une classe de base et dérivée. Les interfaces Go ont été conçues après les protocoles du langage de programmation Smalltalk. Plusieurs sources utilisent le terme duck typing lors de la description des interfaces Go., Bien que le terme duck typing ne soit pas défini avec précision et ne soit donc pas erroné, il implique généralement que la conformité du type n’est pas vérifiée statiquement. Étant donné que la conformité à une interface Go est vérifiée statiquement par le compilateur Go (sauf lors de l’exécution d’une assertion de type), Les auteurs Go préfèrent le terme typage structurel.

La définition d’un type d’interface répertorie les méthodes requises par nom et type. Tout objet de type T pour lequel des fonctions existent correspondant à toutes les méthodes requises de type d’interface I est également un objet de type I. La définition du type T N’a pas besoin (et ne peut pas) d’identifier le type I., Par exemple, si la forme, le carré et le cercle sont définis comme

alors un carré et un cercle sont implicitement une forme et peuvent être affectés à une variable typée en forme.: 263-268 en langage formel, le système d’interface de Go fournit un typage structurel plutôt que nominal. Les Interfaces peuvent intégrer d’autres interfaces avec l’effet de créer une interface combinée qui est satisfaite par exactement les types qui implémentent l’interface intégrée et toutes les méthodes que l’interface nouvellement définie ajoute.,: 270

la bibliothèque standard Go utilise des interfaces pour fournir de la généricité à plusieurs endroits, y compris le système d’entrée / sortie basé sur les concepts de lecteur et D’écrivain.:282-283

en plus d’appeler des méthodes via des interfaces, Go permet de convertir des valeurs d’interface en d’autres types avec une vérification du type d’exécution. Les constructions de langage pour le faire sont l’assertion de type, qui vérifie par rapport à un seul type potentiel, et le commutateur de type, qui vérifie par rapport à plusieurs types.,

l’interface videinterface{} est un cas de base important car il peut se référer à un élément de tout type de béton. Il est similaire à la classe Object en Java ou C# et est satisfait par n’importe quel type, y compris les types intégrés comme int.: 284 le Code utilisant l’interface vide ne peut pas simplement appeler des méthodes (ou des opérateurs intégrés) sur l’objet visé, mais il peut stocker la valeur interface{}, essayer de la convertir en un type plus utile via une assertion de type ou un commutateur de type, ou l’inspecter avec le package reflect., Parce que interface{} peut faire référence à n’importe quelle valeur, c’est un moyen limité d’échapper aux restrictions du typage statique, comme void* en C mais avec des vérifications de type d’exécution supplémentaires.

le typeinterface{}peut être utilisé pour modéliser les données structurées de n’importe quel schéma arbitraire dans Go, telles que les données JSON ou YAML, en les représentant sous la forme d’unmapinterface{} (carte de chaîne à interface vide). Cela décrit récursivement des données sous la forme d’un dictionnaire avec des clés de chaîne et des valeurs de tout type.,

Les valeurs D’Interface sont implémentées à l’aide d’un pointeur vers les données et d’un second pointeur vers les informations de type d’exécution. Comme certains autres types implémentés à l’aide de pointeurs dans Go, les valeurs d’interface sont nil si elles ne sont pas initialisées.

le Paquet systemEdit

Dans le jeu de Go du système de paquets, chaque paquet a un chemin d’accès (par exemple, "compress/bzip2" ou "golang.org/x/net/html") et un nom (par exemple, bzip2 ou html)., Les références aux définitions des autres paquets doivent toujours être préfixées avec le nom de l’autre paquet, et seuls les noms en majuscules des autres paquets sont accessibles: io.Reader est public mais bzip2.reader ne l’est pas. La commandego get peut récupérer des paquets stockés dans un dépôt distant et les développeurs sont encouragés à développer des paquets dans un chemin de base correspondant à un dépôt source (par exemple.,com/user_name/package_name) pour réduire la probabilité de collision de noms avec des ajouts futurs à la bibliothèque standard ou à d’autres bibliothèques externes.

des propositions existent pour introduire une solution de gestion de paquets appropriée pour Go similaire à CPAN pour le système de fret Perl ou Rust ou le système npm de Node.

simultanéité: goroutines et channelsEdit

le langage Go dispose d’installations intégrées, ainsi que d’un support de bibliothèque, pour écrire des programmes simultanés., La concurrence fait référence non seulement au parallélisme du processeur, mais aussi à l’asynchronie: laisser des opérations lentes comme une base de données ou une lecture réseau s’exécuter pendant que le programme effectue d’autres travaux, comme cela est courant dans les serveurs basés sur des événements.

la construction principale de concurrence est la goroutine, un type de processus léger. Un appel de fonction préfixé avec le mot-clé go démarre une fonction dans une nouvelle goroutine., La spécification du langage ne spécifie pas comment les goroutines doivent être implémentées, mais les implémentations actuelles multiplexent les goroutines d’un processus Go sur un plus petit ensemble de threads du système d’exploitation, similaire à la planification effectuée dans Erlang.: 10

alors qu’un paquet de bibliothèque standard avec la plupart des structures de contrôle de concurrence classiques (verrous mutex, etc.) est disponible,:151-152 programmes simultanés idiomatiques préfèrent plutôt les canaux, qui fournissent envoyer des messages entre goroutines., Les tampons facultatifs stockent les messages dans L’ordre FIFO: 43 et permettent d’envoyer des goroutines avant que leurs messages ne soient reçus.

Les canaux sont tapés, de sorte qu’un canal de type chan T ne peut être utilisé que pour transférer des messages de type T. une syntaxe spéciale est utilisée pour les utiliser;<-ch est une expression qui provoque le blocage de la goroutine en cours d’exécution jusqu’à ce qu’une valeur arrive sur le canal ch, tandis que ch<- x envoie la valeur x (bloquant éventuellement jusqu’à ce qu’une autre goroutine reçoive la valeur)., L’instruction select de type commutateur intégrée peut être utilisée pour implémenter une communication non bloquante sur plusieurs canaux; voir ci-dessous pour un exemple. Go a un modèle de mémoire décrivant comment les goroutines doivent utiliser des canaux ou d’autres opérations pour partager des données en toute sécurité.

l’existence d’ensembles de canaux se distingue des langages concurrents de type modèle d’acteur comme Erlang, où les messages sont adressés directement aux acteurs (correspondant aux goroutines)., Le style d’acteur peut être simulé dans Go en maintenant une correspondance un à un entre les goroutines et les canaux, mais le langage permet à plusieurs goroutines de partager un canal ou à une seule goroutine d’envoyer et de recevoir sur plusieurs canaux.: 147

à partir de ces outils, on peut créer des constructions simultanées comme des pools de travailleurs, des pipelines (dans lesquels, par exemple, un fichier est décompressé et analysé lors du téléchargement), des appels en arrière-plan avec timeout, des appels parallèles « sortants » vers un ensemble de services, etc., Les canaux ont également trouvé des utilisations plus éloignées de la notion habituelle de communication interprocessus, comme servir de liste sécurisée pour la concurrence de tampons recyclés, implémenter des coroutines (qui ont contribué à inspirer le nom goroutine) et implémenter des itérateurs.

Les conventions structurelles de Go liées à la concurrence (canaux et entrées de canaux alternatifs) sont dérivées du modèle de processus séquentiels communicants de Tony Hoare., Contrairement aux langages de programmation concurrents précédents tels que Occam ou Limbo (un langage sur lequel le co-concepteur de Go Rob Pike a travaillé), Go ne fournit aucune notion intégrée de concurrence sûre ou vérifiable. Bien que le modèle des processus communicants soit privilégié dans Go, il n’est pas le seul: tous les goroutines d’un programme partagent un seul espace d’adressage. Cela signifie que les objets mutables et les pointeurs peuvent être partagés entre les goroutines; voir § absence de sécurité dans les conditions de concurrence, ci-dessous.,

aptitude à la programmation parallèlemodifier

bien que les fonctionnalités de simultanéité de Go ne visent pas principalement le traitement parallèle, elles peuvent être utilisées pour programmer des machines multi-processeurs à mémoire partagée. Diverses études ont été menées sur l’efficacité de cette approche. L’une de ces études a comparé la taille (en lignes de code) et la vitesse des programmes écrits par un programmeur chevronné ne connaissant pas le langage et les corrections apportées à ces programmes par un expert Go (de L’équipe de développement de Google), faisant de même pour Chapel, Cilk et Intel TBB., L’étude a révélé que les non-experts avaient tendance à écrire des algorithmes de division et de conquête avec une instruction go par récursivité, tandis que l’expert écrivait des programmes de distribution-travail-synchronisation en utilisant un goroutine par processeur. Les programmes de l’expert étaient généralement plus rapides, mais aussi plus longs.

absence de conditions de concurrence safetyEdit

Il n’y a aucune restriction sur la façon dont les goroutines accèdent aux données partagées, ce qui rend les conditions de concurrence possibles., Plus précisément, à moins qu’un programme ne se synchronise explicitement via des canaux ou d’autres moyens, les Écritures d’un goroutine peuvent être partiellement, entièrement ou pas du tout visibles par un autre, souvent sans aucune garantie sur l’ordre des Écritures. En outre, les structures de données internes de Go telles que les valeurs d’interface, les en-têtes de tranche, les tables de hachage et les en-têtes de chaîne ne sont pas à l’abri des conditions de concurrence, de sorte que la sécurité du type et de la mémoire peut être violée dans les programmes multithread qui modifient les instances partagées, Au lieu de la prise en charge du langage, la programmation simultanée sûre repose donc sur des conventions; par exemple, Chisnall recommande un idiome appelé « alias XOR mutable », ce qui signifie que le passage d’une valeur mutable (ou pointeur) sur un canal signale un transfert de propriété sur la valeur à son récepteur.:155

BinariesEdit

l’éditeur de liens dans la chaîne d’outils gc crée des binaires liés statiquement par défaut, donc tous les binaires Go incluent le runtime Go.,

OmissionsEdit

Go omet délibérément certaines fonctionnalités courantes dans d’autres langages, y compris l’héritage (implémentation), la programmation générique, les assertions, l’arithmétique de pointeur, les conversions de type implicites, les unions non marquées et les unions marquées. Les concepteurs n’ont ajouté que les installations sur lesquelles tous les trois étaient d’accord.,

parmi les fonctionnalités de langage omises, les concepteurs argumentent explicitement contre les assertions et l’arithmétique des pointeurs, tout en défendant le choix d’omettre l’héritage de type comme donnant un langage plus utile, encourageant plutôt l’utilisation d’interfaces pour obtenir une répartition dynamique et une composition pour réutiliser le code. La Composition et la délégation sont en fait largement automatisées par l’intégration de structures; selon les chercheurs Schmager et al., cette fonctionnalité  » présente de nombreux inconvénients de l’héritage: elle affecte l’interface publique des objets ,elle n’est pas fine (I.,e, Pas de contrôle au niveau de la méthode sur l’intégration), les méthodes d’objets intégrés ne peuvent pas être cachées et elles sont statiques », ce qui ne rend « pas évident » si les programmeurs en abuseront dans la mesure où les programmeurs dans d’autres langages sont réputés pour abuser de l’héritage.

Les concepteurs expriment une ouverture à la programmation générique et notent que les fonctions intégrées sont en fait génériques de type, mais celles-ci sont traitées comme des cas spéciaux; Pike appelle cela une faiblesse qui peut à un moment donné être modifiée. L’équipe Google a construit au moins un compilateur pour un dialecte Go expérimental avec des génériques, mais ne l’a pas publié., Ils sont également ouverts à la normalisation des moyens d’appliquer la génération de code. En juin 2020, un nouveau projet de document de conception a été publié, qui ajouterait la syntaxe nécessaire pour déclarer les fonctions et types génériques. Un outil de traduction de code go2go a été fourni pour permettre aux utilisateurs d’essayer la nouvelle syntaxe, ainsi qu’une version générique du terrain de jeu en ligne Go.,

initialement omis, le mécanisme de panique / récupération de type exception a finalement été ajouté, que les auteurs de Go conseillent d’utiliser pour les erreurs irrécupérables telles que celles qui devraient arrêter un programme entier ou une demande de serveur, ou comme raccourci pour propager les erreurs dans la pile dans un paquet (mais pas au-delà des limites du paquet;

Leave A Comment