Certains PHPers envisageront de se convertir en Go ou Java. Faisons une simple comparaison entre ces deux langages. Cet article est uniquement à titre de référence !
Langage Go
Par rapport à Java, le langage Go est compilé en code machine puis exécuté directement. Un peu comme le langage C. Parce qu’il ne dispose pas de machine virtuelle, c’est très différent de Java. Il est orienté objet et, dans une certaine mesure, il ne s'agit pas simplement d'un nouveau langage C avec un garbage collection automatique. Du point de vue d'un programmeur Java, il y a des choses qui sont si différentes que l'apprentissage du langage Go devient extrêmement difficile et permet d'acquérir une compréhension plus approfondie des constructions du langage de programmation, ainsi que des objets, des classes et de tout autre élément. Que se passe-t-il avec les composants du langage, même avec Java .
Ce que je veux dire, c'est que si vous comprenez l'implémentation orientée objet dans le langage Go, alors vous comprendrez également les différentes implémentations de ces choses dans le langage Java.
Utiliser ou non le garbage collection
La partie gestion de la mémoire est cruciale dans les langages de programmation. Le langage assembleur vous permet de tout faire, ou plutôt, il vous demande de tout faire. La bibliothèque standard C fournit certaines fonctions de base pour la gestion de la mémoire, mais cela nécessite toujours de les libérer manuellement après avoir appelé malloc pour allouer de la mémoire. La technologie de gestion automatisée de la mémoire a émergé avec C++, Python, Swift et Java. La langue Go en fait également partie.
Pour Java et d'autres langages JVM (y compris l'implémentation JVM de Python), la mémoire est gérée par la JVM. La JVM dispose d'un garbage collection très mature. Le garbage collection s'exécute toujours dans un ou plusieurs threads - en parallèle avec les threads de travail ou en suspendant parfois ces threads de travail pour marquer ces objets inaccessibles, les effacer et disperser les objets détectés. compressés ensemble. Tout ce dont vous devez vous soucier, ce sont les performances.
Le langage Go utilise également cette méthode, mais il existe encore quelques différences subtiles. Le langage Go n'a pas de références, mais il a des pointeurs. Cette différence est très importante. Le langage Go peut être intégré avec du code C supplémentaire Pour des raisons de performances, rien n'est enregistré au moment de l'exécution comme des références. Le pointeur réel est transparent pour le système en cours d’exécution. La mémoire allouée peut toujours être analysée pour collecter des informations d'accessibilité et les objets inutiles peuvent toujours être marqués et effacés, mais la mémoire ne peut pas être déplacée ailleurs pour le compactage.
Le langage Go a un garbage collection mais ce n'est pas un GC complet comme Java car il ne compresse pas la mémoire. Ce n'est pas nécessairement une mauvaise chose. Parce que cela a du sens pour que le serveur fonctionne longtemps sans provoquer de fragmentation de la mémoire. Certains garbage collector JVM ignoreront également l'étape de compactage afin de réduire les pauses du GC lors de l'effacement de l'ancienne génération et n'utiliseront le compactage qu'en dernier recours. Il n’y a pas d’implémentation de cette étape de dernier recours dans Go, ce qui peut poser quelques problèmes dans de rares scénarios. Lorsque vous apprenez cette langue, il est peu probable que vous rencontriez ce problème.
Variables locales
Dans le langage Java, les variables locales (et parfois les objets dans les versions plus récentes) sont stockées sur la pile. Cela est également vrai en C, C++ et dans d'autres langages qui implémentent la pile d'appels elle-même. Go ne fait pas exception, sauf si vous renvoyez simplement un pointeur vers une variable locale à partir d'une fonction. Il s'agit d'une erreur fatale en langage C. Pour Go, le compilateur Go constate que "l'objet" alloué (j'expliquerai pourquoi les guillemets sont utilisés ici plus tard) s'échappe de la méthode et l'alloue (mémoire) en conséquence, donc cet "objet" est dans la fonction Il est toujours vivant après le retour et le pointeur vers celui-ci ne pointe pas vers une mémoire obsolète avec des données peu fiables.
Fermetures
Vous pouvez écrire une fonction à l'intérieur d'une fonction puis renvoyer cette fonction, tout comme un langage fonctionnel (Go est un langage fonctionnel), puis la variable locale est une variable de fermeture dans cette fonction.
Valeur de retour de fonction
Une fonction peut non seulement renvoyer une seule valeur, mais également renvoyer plusieurs valeurs. Cela semble être une mauvaise pratique sans utilisation équitable. Cela est vrai pour Python et Perl. Renvoyer plusieurs valeurs est utile dans certaines situations. Il est principalement utilisé pour les valeurs de retour et les codes « nul » ou d’erreur. De cette façon, l'habitude passée de coder les erreurs dans le type de retour (renvoyant généralement -1 comme code d'erreur comme un appel à la bibliothèque standard C, et d'autres valeurs non négatives représentant d'autres significations) sera remplacée par cette méthode plus lisible. .
Orienté objet
En traitant les fermetures et les fonctions comme des citoyens de première classe, Go peut être au moins aussi orienté objet que JavaScript. Mais en fait, Go possède des interfaces et des structures et peut faire plus. Mais les interfaces et les structures ne sont pas de vraies classes, ce sont des types valeur. Ils sont transmis par valeur, et peu importe où ils sont stockés en mémoire, les données qu'ils stockent ne sont que des données pures, sans en-tête d'objet ou quoi que ce soit qui ressemble à un en-tête d'objet. Les structures en Go sont très similaires aux structures en C : elles peuvent toutes deux contenir des champs, mais elles ne peuvent pas hériter les unes des autres ni contenir de méthodes. L'implémentation orientée objet est légèrement différente.
Au lieu d'insérer la méthode dans la définition de la classe, vous pouvez spécifier la structure lorsque vous définissez la méthode elle-même. Les structures peuvent également contenir d'autres structures. Si le champ que vous souhaitez référencer n'a pas de nom, vous pouvez le référencer par son type, qui deviendra également implicitement le nom du champ. Ou tant que ce champ ou cette méthode appartient à la structure de niveau supérieur, vous pouvez le référencer
Lorsque vous souhaitez spécifier la structure qui peut appeler la méthode, vous pouvez la spécifier vous-même via la structure ou pointer vers un pointeur vers la structure. Si une méthode est appliquée à une structure, la méthode obtient une copie de la structure appelante (qui est passée par valeur). Si la méthode est appliquée à un pointeur vers une structure, alors le pointeur sera transmis (similaire au passage par référence). Dans ce dernier cas, la méthode peut également muter la structure (en ce sens, la structure n'est pas un type valeur, puisque les types valeur sont immuables). Les deux peuvent être utilisés pour répondre aux besoins de l’interface.
La syntaxe de Go est également plus tolérante aux structures et aux pointeurs. En C, vous pouvez utiliser b.a pour accéder au champ a d'une structure que vous possédez. Pour les pointeurs vers des structures en C, vous devez utiliser b->a pour accéder aux mêmes champs. b.a signalera une erreur lors de l’utilisation des pointeurs. Go pense qu'écrire b->a n'a aucun sens (oui, c'est ce que cela signifie). Pourquoi l'opérateur -> donne-t-il l'impression que le code est encombré alors que l'opérateur . La structure peut accéder aux champs de cette manière, elle doit donc également être accessible de cette manière via des pointeurs, ce qui est très logique.
Le type est sur la variable et non sur l'objet
C'est pourquoi je mets des guillemets autour de "objet". Lorsque Go stocke une structure, il s'agit d'un morceau de mémoire. Elle n'a pas d'en-tête d'objet. En fait, la variable contient le type de la valeur. Si la variable est un type structure, nous la connaissons déjà au moment de la compilation. Si la variable est d'un type d'interface, alors la variable pointera vers sa valeur et fera référence au type réel de la valeur.
Implémentation des interfaces
Les interfaces sont très simples et très complexes dans Go. Une interface déclare un ensemble de méthodes que les structures doivent implémenter si elles veulent être compatibles avec l'interface. L'héritage d'interfaces revient à hériter de structures. Ce qui est étrange, c'est que lorsqu'une structure implémente une interface, vous n'avez pas besoin de la spécifier explicitement. En fait, ce n'est pas l'interface qui implémente l'interface, mais cet ensemble de fonctions qui utilise la structure ou le pointeur vers la structure comme récepteur. Si toutes les fonctions de l'interface sont implémentées, alors cette structure implémente l'interface. Si certaines fonctions ne sont pas implémentées, cela signifie que l’implémentation est incomplète.
Pourquoi avons-nous besoin du mot-clé « impléments » en Java mais pas en Go ? Go n'en a vraiment pas besoin car il est entièrement compilé et il n'existe pas de chargeur de classe comme Java qui charge le code compilé séparément pendant l'exécution. Si une structure est censée implémenter une interface mais ne le fait pas, cela sera découvert au moment de la compilation et il n'est pas nécessaire d'indiquer explicitement si l'interface implémente l'interface. Vous pouvez implémenter cela en utilisant la réflexion de Go, ce qui provoquera une erreur d'exécution, mais dans tous les cas, la déclaration du mot-clé 'implements' n'aura aucun effet.
Threads et files d'attente
Le langage Go a des threads et des files d'attente intégrés. Ils sont appelés coroutines et canaux. Pour démarrer une coroutine, il vous suffit d'écrire la fonction go call(), qui sera démarrée dans un autre thread. Bien qu'il existe des méthodes ou des fonctions pour verrouiller des « objets » dans la bibliothèque standard Go, la programmation multithread native utilise des canaux. Channel est un type intégré dans Go, qui est un canal premier entré, premier sorti de taille fixe de tout autre type. Vous pouvez pousser une valeur dans le canal et la coroutine peut extraire la valeur du canal. Si le canal est plein, pousser bloquera ; si le canal est vide, tirer bloquera.
Il y a des erreurs mais aucune exception dans Go
Go a en fait une gestion des exceptions mais il n'est pas utilisé comme en Java. Les exceptions sont appelées « paniques » et sont utilisées lorsqu'il y a une véritable panique dans le code. Du point de vue des règles Java, « panique » est similaire à certaines exceptions se terminant par « …Erreur ». Cet état est renvoyé par un appel système lorsqu'il existe une instance d'exception ou une erreur qui peut être gérée, et les fonctions d'application sont censées gérer cet état selon un modèle similaire.
Il n'y a pas de final, le report le remplace
La gestion des exceptions étroitement couplées est une fonctionnalité que Java implémente avec la fonctionnalité try/catch/finally. En Java, vous pouvez mettre du code qui sera exécuté quoi qu'il arrive dans un bloc final. Go fournit le mot-clé « defer » qui vous permet de spécifier une fonction à appeler avant le retour de la méthode (même si la méthode panique). L'utilisation de Defer pour résoudre le problème ci-dessus le rend moins susceptible aux abus. Vous ne pouvez écrire aucun code exécutable après un appel de fonction différé. Mais en Java, vous pouvez même écrire une instruction return dans le bloc final, ou voir une instruction try très déroutante utilisée pour gérer le code à exécuter dans le bloc final, qui peut également lever une exception. Go tend vers le premier.
Dans l’ensemble, Go est un langage intéressant. Il ne remplace pas Java, même au niveau du langage. Java et Go ne répondent pas au même type de tâches : Java est un langage de développement au niveau de l'entreprise et Go est un langage de programmation au niveau du système.
Tutoriel vidéo Java recommandé : Tutoriel vidéo JAVA
Tutoriel vidéo Go recommandé : Tutoriel vidéo Go
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!