Les génériques, introduits dans Go 1.18, ont révolutionné la manière d'écrire du code réutilisable et de type sécurisé. Les génériques apportent flexibilité et puissance tout en conservant la philosophie de simplicité de Go. Cependant, comprendre les nuances, les avantages et la façon dont les génériques se comparent aux approches traditionnelles (comme interface{} ) nécessite un examen plus approfondi.
Explorons les subtilités des génériques, approfondissons les contraintes, comparons les génériques à l'interface{} et démontrons leurs applications pratiques. Nous aborderons également les considérations de performances et les implications en matière de taille binaire. Allons-y !
Qu’est-ce que les génériques ?
Les génériques permettent aux développeurs d'écrire des fonctions et des structures de données pouvant fonctionner sur n'importe quel type tout en maintenant la sécurité des types. Au lieu de s'appuyer sur interface{}, qui implique des assertions de type au moment de l'exécution, les génériques vous permettent de spécifier un ensemble de contraintes qui dictent les opérations autorisées sur les types.
Syntaxe
func FunctionName[T TypeConstraint](parameterName T) ReturnType { // Function body using T }
T : Un paramètre de type, représentant un espace réservé pour le type.
TypeConstraint : restreint le type de T à un type spécifique ou à un ensemble de types.
parameterName T : Le paramètre utilise le type générique T.
ReturnType : La fonction peut également renvoyer une valeur de type T.
Exemple
func Sum[T int | float64](a, b T) T { return a + b }
func Sum : Déclare le nom de la fonction, Sum
[T int | float64] : Spécifie une liste de paramètres de type qui introduit T comme paramètre de type, limité à des types spécifiques (int ou float64). La fonction Somme ne peut prendre que des paramètres int ou float64, pas en combinaison, les deux doivent être soit int, soit float64. Nous explorerons cela plus en détail dans les sections ci-dessous.
(a, b T): Déclare deux paramètres, a et b, tous deux de type T (le type générique ).
T : Spécifie le type de retour de la fonction, qui correspond au paramètre de type T.
Contraintes : éléments constitutifs des génériques
Les contraintes définissent quelles opérations sont valides pour un type générique. Go fournit des outils puissants pour les contraintes, y compris le package de contraintes expérimentales (golang.org/x/exp/constraints).
Contraintes intégrées
Go a introduit des contraintes intégrées avec les génériques pour assurer la sécurité des types tout en permettant une flexibilité dans la définition de code réutilisable et générique. Ces contraintes permettent aux développeurs d'appliquer des règles sur les types utilisés dans les fonctions ou types génériques.
Go a des contraintes intégrées ci-dessous
- any : représente n'importe quel type. C'est un alias pour interface{}. Ceci est utilisé lorsqu'aucune contrainte n'est nécessaire
func FunctionName[T TypeConstraint](parameterName T) ReturnType { // Function body using T }
- comparable : autorise les types qui prennent en charge la comparaison d'égalité (== et !=). Utile pour les clés de cartes, la détection des doublons ou les contrôles d'égalité. Cela ne peut pas être utilisé pour les cartes, les tranches et les fonctions, car ces types ne prennent pas en charge la comparaison directe.
func Sum[T int | float64](a, b T) T { return a + b }
Contraintes expérimentales
- constraints.Complex : autorise les types numériques complexes (complex64 et complex128).
- constraints.Float : autorise les types numériques float (float32 et float64)
- constraints.Integer : autorise tout entier signé et non signé (int8, int16, int32, int64, int, uint8, uint16, uint32, uint64 et uint)
- constraints.Signed : autorise tout entier signé (int8, int16, int32, int64 et int)
- constraints.Unsigned : autorise tout entier non signé (uint8, uint16, uint32, uint64 et uint).
- constraint.Ordered : autorise les types qui permettent la comparaison (<.>, >=), tous les types numériques et chaînes sont pris en charge (int, float64, string, etc.).
func PrintValues[T any](values []T) { for _, v := range values { fmt.Println(v) } }
Contraintes personnalisées
Les contraintes personnalisées sont des interfaces qui définissent un ensemble de types ou de comportements de type qu'un paramètre de type générique doit satisfaire. En créant vos propres contraintes, nous pouvons ;
Limiter les types à un sous-ensemble spécifique, tel que les types numériques.
Exiger des types pour implémenter des méthodes ou des comportements spécifiques.
Ajoutez plus de contrôle et de spécificité à vos fonctions et types génériques.
Syntaxe
func CheckDuplicates[T comparable](items []T) []T { seen := make(map[T]bool) duplicates := []T{} for _, item := range items { if seen[item] { duplicates = append(duplicates, item) } else { seen[item] = true } } return duplicates }
Exemple
import ( "golang.org/x/exp/constraints" "fmt" ) func SortSlice[T constraints.Ordered](items []T) []T { sorted := append([]T{}, items...) // Copy slice sort.Slice(sorted, func(i, j int) bool { return sorted[i] <p><strong><em>La fonction Somme</em></strong> peut être appelée en utilisant uniquement les paramètres int, int64 et float64.</p> <h3> Contraintes par méthode </h3> <p>Si vous souhaitez imposer qu'un type doive implémenter certaines méthodes, vous pouvez le définir en utilisant ces méthodes.<br> </p> <pre class="brush:php;toolbar:false">type Numeric interface { int | float64 | uint }
La contrainte Formatter requiert que tout type utilisé comme T doit avoir une méthode Format qui renvoie un chaîne.
Combinaison de contraintes
Les contraintes personnalisées peuvent combiner des ensembles de types et des exigences de méthode
type Number interface { int | int64 | float64 } func Sum[T Number](a, b T) T { return a + b }
Cette contrainte inclut à la fois des types spécifiques (int, float54) et nécessite la présence d'une méthode abs.
Génériques vs interface{}
Avant l'introduction des génériques, l'interface{} était utilisée pour obtenir de la flexibilité. Cependant, cette approche a des limites.
Sécurité
interface{} : s'appuie sur des assertions de type d'exécution, augmentant le risque d'erreurs au moment de l'exécution.
Génériques : offre une sécurité de type au moment de la compilation, détectant les erreurs dès le début du développement.
Performance
interface{} : plus lente en raison de vérifications de type d'exécution supplémentaires.
Génériques : plus rapide, car le compilateur génère des chemins de code optimisés spécifiques aux types.
Lisibilité du code
interface{} : souvent verbeuse et moins intuitive, ce qui rend le code plus difficile à maintenir.
Génériques : une syntaxe plus propre conduit à un code plus intuitif et maintenable.
Taille binaire
interface{} : génère des binaires plus petits car elle ne duplique pas le code pour différents types.
Génériques : augmente légèrement la taille du binaire en raison de la spécialisation du type pour de meilleures performances.
Exemple
func FunctionName[T TypeConstraint](parameterName T) ReturnType { // Function body using T }
Le code fonctionne bien, l'assertion de type est une surcharge. La fonction Add peut être appelée avec n'importe quel argument, les paramètres a et b peuvent être de types différents, mais le code plantera lors de l'exécution.
func Sum[T int | float64](a, b T) T { return a + b }
Les génériques éliminent le risque de panique d'exécution causée par des assertions de type incorrectes et améliorent la clarté.
Performance
Les génériques produisent du code spécialisé pour chaque type, conduisant à de meilleures performances d'exécution par rapport à l'interface{}.
Taille binaire
Un compromis existe : les génériques augmentent la taille des binaires en raison de la duplication de code pour chaque type, mais cela est souvent négligeable par rapport aux avantages.
Limites des génériques Go
Complexité des contraintes : Même si les contraintes ressemblent à des contraintes.Ordonnées, elles simplifient les cas d'utilisation courants, la définition de contraintes hautement personnalisées peut devenir verbeuse.
Aucune inférence de type dans les structures : Contrairement aux fonctions, vous devez spécifier explicitement le paramètre de type pour les structures.
func PrintValues[T any](values []T) { for _, v := range values { fmt.Println(v) } }
Limité aux contraintes de temps de compilation : Les génériques Go se concentrent sur la sécurité au moment de la compilation, tandis que des langages comme Rust offrent des contraintes plus puissantes utilisant des durées de vie et des traits.
Faisons un benchmark – Mieux fait que dit
Nous allons implémenter une file d'attente simple avec à la fois une interface{} et générique et comparer les résultats.
Interface{} Implémentation de la file d'attente
func CheckDuplicates[T comparable](items []T) []T { seen := make(map[T]bool) duplicates := []T{} for _, item := range items { if seen[item] { duplicates = append(duplicates, item) } else { seen[item] = true } } return duplicates }
Implémentation de file d'attente générique
import ( "golang.org/x/exp/constraints" "fmt" ) func SortSlice[T constraints.Ordered](items []T) []T { sorted := append([]T{}, items...) // Copy slice sort.Slice(sorted, func(i, j int) bool { return sorted[i] <pre class="brush:php;toolbar:false">type Numeric interface { int | float64 | uint }
Analyse des résultats
Durée d'exécution :
L'implémentation générique est environ 63,64 % plus rapide que la version interface{} car elle évite les assertions de type d'exécution et fonctionne directement sur le type donné.Allocations :
La version interface{} effectue 3 fois plus d'allocations, principalement en raison du boxing/unboxing lors de l'insertion et de la récupération de valeurs. Cela ajoute des frais généraux à la collecte des ordures.
Pour les charges de travail plus importantes, telles qu'un million d'opérations de mise en file d'attente/retrait de la file d'attente, l'écart de performances se creuse. Les applications du monde réel ayant des exigences de débit élevé (par exemple, files d'attente de messages, planificateurs de tâches) bénéficient considérablement des génériques.
Pensées finales
Generics in Go établit un équilibre entre puissance et simplicité et offre une solution pratique pour écrire du code réutilisable et sécurisé. Bien qu'il ne soit pas aussi riche en fonctionnalités que Rust ou C, il s'aligne parfaitement sur la philosophie minimaliste de Go. Comprendre les contraintes telles que les contraintes. Commander et exploiter efficacement les génériques peut grandement améliorer la qualité et la maintenabilité du code.
À mesure que les génériques continuent d’évoluer, ils sont destinés à jouer un rôle central dans l’écosystème de Go. Alors plongez, expérimentez et adoptez la nouvelle ère de sécurité des types et de flexibilité dans la programmation Go !
Consultez le référentiel github pour quelques exemples sur les génériques.
sadananddodawadakar
/
AllerGénériques
Le référentiel contient des exemples fonctionnels de génériques go
Go Generics : référentiel d'exemples complet
Bienvenue dans le Référentiel Go Generics ! Ce référentiel est une ressource unique pour comprendre, apprendre et maîtriser les génériques dans Go, introduits dans la version 1.18. Les génériques apportent la puissance des paramètres de type à Go, permettant aux développeurs d'écrire du code réutilisable et sécurisé sans compromettre les performances ou la lisibilité.
Ce référentiel contient des exemples soigneusement sélectionnés qui couvrent un large éventail de sujets, de la syntaxe de base aux modèles avancés et aux cas d'utilisation pratiques. Que vous soyez un développeur Go débutant ou expérimenté, cette collection vous aidera à exploiter efficacement les génériques dans vos projets.
? Qu'y a-t-il à l'intérieur
? Programmes génériques de base
Ces exemples présentent les concepts fondamentaux des génériques, vous aidant à comprendre la syntaxe et les fonctionnalités principales :
- GenericMap : démontre une fonction de carte générique pour transformer des tranches de tout type.
- Swap : Un exemple simple mais puissant d'échange générique de deux valeurs.
- FilterSlice : montre comment filtrer…
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!

Go utilise le package "Encoding / Binary" pour le codage et le décodage binaires. 1) Ce package fournit des fonctions Binary.Write et Binary.read pour les données d'écriture et de lecture. 2) Faites attention au choix du bon endian (comme Bigendian ou Littleendian). 3) L'alignement des données et la gestion des erreurs sont également essentiels pour garantir l'exactitude et les performances des données.

Les "octets" packageofferser efficace pour la manière

Theencoding/binarypackageinGoiseffectiveforoptimizingbinaryoperationsduetoitssupportforendiannessandefficientdatahandling.Toenhanceperformance:1)Usebinary.NativeEndianfornativeendiannesstoavoidbyteswapping.2)BatchReadandWriteoperationstoreduceI/Oover

Le package des octets GO est principalement utilisé pour traiter efficacement les tranches d'octets. 1) Utilisation de Bytes.Buffer peut effectuer efficacement l'épissage de chaîne pour éviter une allocation de mémoire inutile. 2) Les octets. La fonction égale est utilisée pour comparer rapidement les tranches d'octets. 3) Les fonctions Bytes.Index, Bytes.Split et Bytes.ReplaceALL peuvent être utilisées pour rechercher et manipuler des tranches d'octets, mais les problèmes de performances doivent être prêts à l'attention.

Le package d'octets offre une variété de fonctions pour traiter efficacement les tranches d'octets. 1) Utilisez les octets.Contient pour vérifier la séquence d'octets. 2) Utilisez des octets.split pour diviser les tranches d'octets. 3) Remplacez les octets de séquence d'octets. Replace. 4) Utilisez des bytes.join pour connecter plusieurs tranches d'octets. 5) Utilisez des bytes.buffer pour créer des données. 6) Bytes combinés. MAP pour le traitement des erreurs et la vérification des données.

Le package d'encodage / binaire de Go est un outil pour le traitement des données binaires. 1) Il prend en charge l'ordre des octets endian des petits et grandes enlans et peut être utilisé dans les protocoles de réseau et les formats de fichiers. 2) Le codage et le décodage des structures complexes peuvent être gérés via des fonctions de lecture et d'écriture. 3) Faites attention à la cohérence de l'ordre des octets et du type de données lors de l'utilisation, en particulier lorsque les données sont transmises entre différents systèmes. Ce package convient au traitement efficace des données binaires, mais nécessite une gestion minutieuse des tranches et des longueurs d'octets.

Les "octets" emballent la manière

Go'sstringspackageincludessentialfunctionslikecontains, trimspace, fen spin, andReplaceALL.1) contiennent une visualisation de coche


Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Dreamweaver CS6
Outils de développement Web visuel

PhpStorm version Mac
Le dernier (2018.2.1) outil de développement intégré PHP professionnel

Listes Sec
SecLists est le compagnon ultime du testeur de sécurité. Il s'agit d'une collection de différents types de listes fréquemment utilisées lors des évaluations de sécurité, le tout en un seul endroit. SecLists contribue à rendre les tests de sécurité plus efficaces et productifs en fournissant facilement toutes les listes dont un testeur de sécurité pourrait avoir besoin. Les types de listes incluent les noms d'utilisateur, les mots de passe, les URL, les charges utiles floues, les modèles de données sensibles, les shells Web, etc. Le testeur peut simplement extraire ce référentiel sur une nouvelle machine de test et il aura accès à tous les types de listes dont il a besoin.

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

MinGW - GNU minimaliste pour Windows
Ce projet est en cours de migration vers osdn.net/projects/mingw, vous pouvez continuer à nous suivre là-bas. MinGW : un port Windows natif de GNU Compiler Collection (GCC), des bibliothèques d'importation et des fichiers d'en-tête librement distribuables pour la création d'applications Windows natives ; inclut des extensions du runtime MSVC pour prendre en charge la fonctionnalité C99. Tous les logiciels MinGW peuvent fonctionner sur les plates-formes Windows 64 bits.
