国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Maison développement back-end Golang Démystifier les OTP?: la logique derrière la génération de jetons hors ligne

Démystifier les OTP?: la logique derrière la génération de jetons hors ligne

Dec 12, 2024 pm 10:23 PM

Bonjour ! Un autre soir, en rentrant chez moi, j'ai décidé de consulter ma bo?te aux lettres. Je ne parle pas de ma bo?te de réception e-mail, mais de la bo?te à l'ancienne où le facteur met les lettres physiques. Et à ma grande surprise, j'y ai trouvé une enveloppe avec quelque chose à l'intérieur ! En l'ouvrant, j'ai passé quelques instants à espérer qu'il s'agissait de la lettre de Poudlard retardée de plusieurs décennies. Mais ensuite j'ai d? revenir sur Terre, une fois que j'ai remarqué qu'il s'agissait d'une lettre ennuyeuse ? d'adulte ? de la banque. J'ai parcouru le texte et réalisé que ma banque ? 100 % numérique ? pour cool kids avait été rachetée par le plus gros acteur du marché local. Et en signe d'un nouveau départ, ils ont ajouté ceci à l'enveloppe?:

Demystifying OTPs: the logic behind the offline generation of tokens

à c?té des instructions sur la fa?on de l'utiliser.

Si vous êtes comme moi et que vous n'avez jamais découvert une telle innovation technologique, permettez-moi de partager ce que j'ai appris de la lettre?: les nouveaux propriétaires ont décidé d'appliquer les politiques de sécurité de leur entreprise, ce qui signifie que tous les utilisateurs les comptes auront désormais le MFA activé (félicitations pour cela, d'ailleurs). Et l'appareil que vous pouvez voir ci-dessus génère des jetons uniques à 6 chiffres qui sont utilisés comme deuxième facteur lors de la connexion à votre compte bancaire. Fondamentalement, de la même manière que des applications comme Authy, Google Authenticator ou 2FAS, mais sous une forme physique.

J'ai donc essayé et le processus de connexion s'est déroulé sans problème?: l'appareil m'a montré un code à 6 chiffres, je l'ai saisi dans mon application bancaire, et cela m'a permis d'accéder. Hourra?! Et puis quelque chose m’a frappé : comment ?a marche ? Il n'est pas possible qu'il soit connecté à Internet d'une manière ou d'une autre, mais il parvient à générer des codes corrects qui sont acceptés par le serveur de ma banque. Hm... Pourrait-il contenir une carte SIM ou quelque chose de similaire à l'intérieur ? Pas question !

Réalisant que ma vie ne sera plus jamais la même, j'ai commencé à m'interroger sur les applications que j'ai mentionnées ci-dessus (Authy et amis) ? Mon chercheur intérieur a été réveillé, j'ai donc mis mon téléphone en mode avion et, à ma grande surprise, j'ai réalisé qu'ils fonctionnent parfaitement hors ligne : ils continuent de générer des codes qui sont acceptés par les serveurs des applications. Intéressant?!

Je ne suis pas s?r pour vous, mais j'ai toujours pris le flux de jetons unique pour acquis et je n'y ai jamais vraiment réfléchi (surtout en raison du fait que de nos jours, il est rare que mon téléphone n'ait pas Internet à moins que Je fais des aventures en plein air), c'est donc la cause première de ma surprise. Sinon, il est tout à fait logique du point de vue de la sécurité de fonctionner de cette manière, car le processus de génération est purement local, donc à l'abri des acteurs externes. Mais comment ?a marche ?

Eh bien, les technologies modernes comme Google ou ChatGPT permettent de trouver facilement la réponse. Mais ce problème technique m'a semblé amusant, alors j'ai décidé de l'essayer et de le résoudre par moi-même d'abord.

Exigences

Commen?ons par ce que nous avons?:

  • un appareil hors ligne qui génère des codes à 6 chiffres
  • un serveur qui accepte ces codes, les valide et donne un signal vert s'ils sont corrects

La partie validation du serveur laisse entendre que le serveur doit être capable de générer le même code que l'appareil hors ligne pour les comparer. Hm..?a peut être utile.

Mes observations ultérieures de mon nouveau "jouet" m'ont apporté encore plus de découvertes?:

  • Si je l'éteins puis l'éteins, je peux généralement voir le même code qu'avant
  • Cependant, de temps en temps, cela change

La seule explication logique que j'ai pu trouver est que ces codes ont une certaine durée de vie. J'aimerais raconter une histoire de moi essayant de compter la durée à la manière "1-2-3-...-N", mais ce ne sera pas vrai?: j'ai re?u un gros indice des applications comme Authy and Co, où j'ai vu le TTL de 30 secondes. Bonne trouvaille, ajoutons ceci à la liste des faits connus.

Résumons les exigences que nous avons jusqu'à présent?:

  • Génération de code prévisible (plut?t qu'aléatoire) au format 6 chiffres
  • la logique de génération doit être reproductible, ce qui permet d'obtenir le même résultat quelle que soit la plateforme
  • la durée de vie du code est de 30 secondes, ce qui signifie que dans ce laps de temps l'algorithme de génération produit la même valeur

La grande question

Très bien, mais la question principale reste sans réponse?: comment se fait-il que l'application hors ligne puisse générer la valeur qui correspondra à celle de l'autre application?? Qu’ont-ils en commun ?

Si vous êtes dans l'univers du Seigneur des Anneaux, vous vous souviendrez peut-être de la fa?on dont Bilbo a joué à un jeu d'énigmes avec Gollum et a réussi à résoudre celui-ci?:

Cette chose que tout dévore?:
Oiseaux, bêtes, arbres, fleurs?;
Ronge le fer, mord l'acier?;
Broie les pierres dures en farine?;
Tue le roi, ruine la ville,
Et bat la haute montagne.

Alerte spoiler, mais M. Baggins a eu de la chance et a accidentellement trouvé la bonne réponse?: "Il est temps?!". Croyez-le ou non, mais c'est exactement la réponse à notre énigme?: 2 applications (ou plus) ont accès à la même heure tant qu'elles ont une horloge intégrée. Ce dernier ne pose plus de problème de nos jours, et l’appareil en question est suffisamment grand pour l’accueillir. Regardez autour de vous et il y a de fortes chances que l’heure sur votre montre, votre téléphone portable, votre téléviseur, votre four et votre horloge murale soit la même. Nous sommes dans quelque chose ici, il semble que nous ayons trouvé la base de l'informatique OTP (mot de passe à usage unique) !

Défis

Compter sur le temps comporte son propre ensemble de défis?:

  • Fuseau horaire - lequel utiliser??
  • les horloges ont tendance à se désynchroniser, et c'est un gros défi dans les systèmes distribués

Abordons-les un par un?:

  • fuseau horaire?: la solution la plus simple ici est de s'assurer que tous les appareils reposent sur le même fuseau horaire, et UTC peut être un bon candidat indépendant de l'emplacement
  • en ce qui concerne les horloges qui se désynchronisent?: en fait, nous n'aurons peut-être même pas besoin de le résoudre, mais plut?t de l'accepter comme quelque chose d'inévitable, tant que la dérive se situe dans la seconde ou deux, ce qui pourrait être tolérable compte tenu du TTL de 30 secondes. Le fabricant du matériel de l'appareil devrait être en mesure de prédire quand une telle dérive sera atteinte, de sorte que l'appareil l'utilisera comme date d'expiration et que la banque les remplacera simplement par les nouveaux, ou aura un moyen de les connecter. au réseau pour calibrer l’horloge. Du moins, c'est ce que je pense ici.

Mise en ?uvre

Ok, c'est réglé, essayons donc d'implémenter la toute première version de notre algorithme en utilisant le temps comme base. Puisque nous sommes intéressés par un résultat à 6 chiffres, il semble judicieux de s'appuyer sur un horodatage plut?t que sur une date lisible par l'homme. Commen?ons par là?:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

Selon la documentation Go, le .Unix() renvoie

le nombre de secondes écoulées depuis le 1er janvier 1970 UTC.

Voici ce qui est imprimé sur le terminal?:

Current timestamp:  1733691162

C'est un bon début, mais si nous réexécutons ce code, la valeur de l'horodatage changera, alors que nous aimerions la garder stable pendant 30 secondes. Eh bien, c'est un jeu d'enfant, divisons-le par 30 et utilisons cette valeur comme base?:

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

Exécutons?:

Current timestamp:  1733691545
Base:  57789718

Et encore?:

Current timestamp:  1733691552
Base:  57789718

La valeur de base reste la même. Attendons un peu et réexécutons?:

Current timestamp:  1733691571
Base:  57789719

La valeur de base a changé, une fois la fenêtre de 30 secondes écoulée - bon travail?!

Si la logique ??diviser par 30?? n'a pas de sens, laissez-moi l'expliquer avec un exemple simple?:

  • imaginez que notre horodatage renvoie 1
  • Si on divise 1 par 30, le résultat sera 0, car lorsque l'on utilise un langage de programmation strictement typé, diviser un entier par un entier renvoie un autre entier, qui ne se soucie pas de la partie flottante
  • cela signifie que pendant les 30 prochaines secondes, nous obtiendrons 0 alors que l'horodatage est compris entre 0 et 29
  • Une fois que l'horodatage atteint la valeur 30, le résultat de la division est 1, jusqu'à 60 (où il devient 2), et ainsi de suite

J'espère que cela a plus de sens maintenant.

Cependant, toutes les exigences ne sont pas encore satisfaites, car nous avons besoin d'un résultat à 6 chiffres, alors que la base actuelle a 8 chiffres à partir d'aujourd'hui, mais à un moment donné dans le futur, elle pourrait atteindre 9 chiffres, et ainsi de suite. . Eh bien, utilisons une autre astuce mathématique simple?: divisons la base par 1?000?000 et obtenons le reste, qui aura toujours exactement 6 chiffres, car le rappel peut être n'importe quel nombre de 0 à 999?999, mais jamais plus grand?:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

La partie fmt.Sprintf(" d", code) ajoute des zéros non significatifs au cas où notre valeur de code aurait moins de 6 chiffres. Par exemple, 1234 sera converti en 001234.
Le code complet de cet article peut être trouvé ici.

Exécutons ce code?:

Current timestamp:  1733691162

Très bien, nous obtenons notre code à 6 chiffres, hourra?! Mais quelque chose ne va pas ici, n'est-ce pas ? Si je vous donne ce code et que vous l'exécutez en même temps que moi, vous obtiendrez le même code que moi. Cela n'en fait pas un mot de passe sécurisé à usage unique, n'est-ce pas?? Voici une nouvelle exigence?:

  • le résultat devrait être différent selon les utilisateurs

Bien s?r, certaines collisions sont inévitables si nous avons plus d'un million d'utilisateurs, car il s'agit du maximum de valeurs uniques possibles pour 6 chiffres. Mais ce sont des collisions rares et techniquement inévitables, et non un défaut de conception d’algorithme comme celui que nous avons actuellement.

Je ne pense pas que des astuces mathématiques intelligentes nous aideront ici à elles seules?: si nous avons besoin de résultats séparés par utilisateur, nous avons besoin d'un état spécifique à l'utilisateur pour y parvenir. En tant qu'ingénieurs et, en même temps, utilisateurs de nombreux services, nous savons que pour accorder l'accès à leurs API, les services s'appuient sur des clés privées, uniques par utilisateur. Introduisons également une clé privée pour notre cas d'utilisation afin de distinguer les utilisateurs.

Clé privée

Une logique simple pour générer des clés privées sous forme d'entiers compris entre 1?000?000 et 999?999?999?:

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

Nous utilisons la carte pkDb comme moyen d'éviter les doublons entre les clés privées, et si le doublon a été détecté, nous exécutons à nouveau la logique de génération jusqu'à ce que nous obtenions un résultat unique.

Exécutons ce code pour obtenir l'exemple de clé privée?:

Current timestamp:  1733691545
Base:  57789718

Utilisons cette clé privée dans notre logique de génération de code pour nous assurer que nous obtenons des résultats différents par clé privée. Puisque notre clé privée est de type entier, la chose la plus simple que nous puissions faire est de l'ajouter à la valeur de base et de conserver l'algorithme restant tel quel?:

Current timestamp:  1733691552
Base:  57789718

Assurons-nous qu'il produit des résultats différents pour différentes clés privées?:

Current timestamp:  1733691571
Base:  57789719

Le résultat semble tel que nous le souhaitions et l'attendions?:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds:
base := current / 30
fmt.Println("Base: ", base)

// makes sure it has only 6 digits:
code := base % 1_000_000

// adds leading zeros if necessary:
formattedCode := fmt.Sprintf("%06d", code)
fmt.Println("Code: ", formattedCode)

Fonctionne à merveille?! Cela signifie que la clé privée doit être injectée dans l'appareil qui génère les codes avant d'être envoyée aux utilisateurs comme moi : cela ne devrait pas poser de problème du tout pour les banques.

Avons-nous terminé maintenant?? Enfin, seulement si nous sommes satisfaits du scénario artificiel que nous avons utilisé. Si vous avez déjà activé le MFA pour des services/sites Web sur lesquels vous avez un compte, vous avez peut-être remarqué que la ressource Web vous demande de scanner le code QR avec l'application de deuxième facteur de votre choix (Authy, Google Authenticator, 2FAS, etc. ) qui saisira le code secret dans votre application et commencera à générer un code à 6 chiffres à partir de ce moment. Alternativement, il est possible de saisir le code manuellement.

J'en parle pour mentionner qu'il est possible de jeter un ?il au format des vraies clés privées utilisées dans l'industrie. Il s'agit généralement de cha?nes codées en Base32 de 16 à 32 caractères qui ressemblent à ceci?:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

Comme vous pouvez le constater, ceci est assez différent des clés privées entières que nous avons utilisées, et l'implémentation actuelle de notre algorithme ne fonctionnera pas si nous devons passer à ce format. Comment pouvons-nous ajuster notre logique??

Clé privée sous forme de cha?ne

Commen?ons par une approche simple?: notre code ne se compilera pas, à cause de cette ligne?:

Current timestamp:  1733691162

car pk est désormais de type string. Alors pourquoi ne pas le convertir en entier?? Bien qu'il existe des moyens bien plus élégants et performants de le faire, voici la chose la plus simple que j'ai trouvée?:

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

Ceci est fortement inspiré de l'implémentation Java hashCode() pour le type de données String, ce qui le rend suffisant pour notre scénario.

Voici la logique ajustée?:

Current timestamp:  1733691545
Base:  57789718

Voici la sortie du terminal?:

Current timestamp:  1733691552
Base:  57789718

Bien, le code à 6 chiffres est là, bon travail. Attendons d'arriver à la fenêtre horaire suivante et exécutons-la à nouveau?:

Current timestamp:  1733691571
Base:  57789719

Hm...?a marche, mais le code est, en gros, l'incrément de la valeur précédente, ce qui n'est pas bon, car de cette fa?on les OTP sont prévisibles, et avoir sa valeur et savoir à quelle heure il appartient, c'est très simple pour commencer à générer les mêmes valeurs sans avoir besoin de conna?tre la clé privée. Voici le pseudocode simple de ce hack?:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds:
base := current / 30
fmt.Println("Base: ", base)

// makes sure it has only 6 digits:
code := base % 1_000_000

// adds leading zeros if necessary:
formattedCode := fmt.Sprintf("%06d", code)
fmt.Println("Code: ", formattedCode)

où keepWithinSixDigits s'assurera qu'après 999?999, la valeur suivante est 000?000 et ainsi de suite pour maintenir la valeur dans la limite des possibilités à 6 chiffres.

Comme vous pouvez le constater, il s’agit d’une grave faille de sécurité. Pourquoi cela arrive-t-il ? Si l'on regarde la logique de calcul de base, nous verrons qu'elle repose sur 2 facteurs?:

  • horodatage actuel divisé par 30
  • hachage de la clé privée

Le hachage produit la même valeur pour la même clé, sa valeur est donc constante. Quant au /30 actuel, il a la même valeur pendant 30 secondes, mais une fois la fenêtre passée, la valeur suivante sera l'incrément de la précédente. Ensuite, la base % 1_000_000 se comporte comme nous le voyons. Notre implémentation précédente (avec des clés privées sous forme d'entiers) présentait la même vulnérabilité, mais nous ne l'avons pas remarqué - le manque de tests est à blamer.

Nous devons transformer le courant / 30 en quelque chose pour rendre le changement de sa valeur plus visible.

Valeurs OTP distribuées

Il existe plusieurs fa?ons d'y parvenir, et quelques astuces mathématiques intéressantes existent, mais à des fins éducatives, donnons la priorité à la lisibilité de la solution que nous utiliserons?: extrayons le courant / 30 dans une base de variables distincte et incluons dans la logique de calcul de hachage?:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

De cette fa?on, même si la base changera de 1 toutes les 30 secondes, après avoir été utilisée dans la logique de la fonction hash(), le poids du diff augmentera en raison de la série de multiplications effectuées.

Voici l'exemple de code mis à jour?:

Current timestamp:  1733691162

Exécutons?:

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

Boum ! Comment se fait-il que nous ayons obtenu la valeur négative ici?? Eh bien, il semble que nous ayons manqué de plages int64, nous avons donc plafonné les valeurs à moins et avons recommencé - mes collègues Java le connaissent grace au comportement hashCode(). La solution est simple?: prenons la valeur absolue du résultat, donc le signe moins est ignoré?:

Current timestamp:  1733691545
Base:  57789718

Voici un exemple de code complet avec le correctif?:

Current timestamp:  1733691552
Base:  57789718

Exécutons?:

Current timestamp:  1733691571
Base:  57789719

Exécutons-le à nouveau pour nous assurer que les valeurs OTP sont distribuées maintenant?:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds:
base := current / 30
fmt.Println("Base: ", base)

// makes sure it has only 6 digits:
code := base % 1_000_000

// adds leading zeros if necessary:
formattedCode := fmt.Sprintf("%06d", code)
fmt.Println("Code: ", formattedCode)

Bien, enfin une solution décente?!

En fait, c'est à ce moment-là que j'ai arrêté mon processus de mise en ?uvre manuelle, car j'ai eu ma part de plaisir et j'ai appris quelque chose de nouveau. Cependant, ce n’est ni la meilleure solution ni celle avec laquelle je partirais vivre. Entre autres choses, il présente un gros défaut?: comme vous pouvez le constater, notre logique traite toujours de grands nombres en raison de la logique de hachage et des valeurs d'horodatage, ce qui signifie qu'il est très peu probable que nous puissions générer des résultats commen?ant par 1 ou plus de zéros?: par exemple, 012345 , 001234, etc., même s'ils sont totalement valides. Pour cette raison, il nous manque 100 000 valeurs possibles, ce qui représente 10 % du nombre possible de résultats de l'algorithme – les chances de collisions sont ainsi plus élevées. Pas cool !

Où aller à partir d'ici

Je n'entrerai pas dans les détails de l'implémentation utilisée dans les applications réelles, mais pour ceux qui sont curieux, je partagerai deux RFC qui valent la peine d'être consultées?:

  • HOTP?: un algorithme de mot de passe à usage unique basé sur HMAC
  • TOTP?: algorithme de mot de passe à usage unique basé sur le temps

Et voici l'implémentation du pseudocode qui fonctionnera comme prévu en fonction des RFC ci-dessus?:

Current timestamp:  1733692423
Base:  57789747
Code:  789747

Comme vous pouvez le voir, nous en sommes très proches, mais l'algorithme d'origine utilise un hachage plus avancé (HMAC-SHA1 dans cet exemple) et effectue quelques opérations au niveau du bit pour normaliser la sortie.

Considérations de sécurité?: réutiliser plut?t que construire soi-même

Cependant, il y a encore une chose que j'aimerais aborder avant de mettre fin à cette journée?: la sécurité. Je vous encourage fortement à ne pas implémenter la logique de génération d'OTP par vous-même, car de nombreuses bibliothèques le font pour nous. La marge d’erreur est énorme, et la vulnérabilité qui sera découverte et exploitée par les mauvais acteurs est proche.

Même si vous ma?trisez la logique de génération et la couvrez de tests, il y a d'autres choses qui peuvent mal tourner. Par exemple, combien pensez-vous qu’il faudra pour forcer brutalement le code à 6 chiffres?? Expérimentons?:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

Exécutons ce code?:

Current timestamp:  1733691162

Et encore une fois?:

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

Comme vous pouvez le voir, il faut environ 70 ms pour deviner le code via une simple boucle for de for?age brut. C'est 400 fois plus rapide que la durée de vie de l'OTP?! Le serveur de l'application/du site Web utilisant le mécanisme OTP doit empêcher cela, par exemple en n'acceptant pas de nouveaux codes pendant les 5 ou 10 secondes suivantes après 3 tentatives infructueuses. De cette fa?on, l'attaquant n'obtient que 18 ou 9 tentatives dans la fenêtre de 30 secondes, ce qui n'est pas suffisant pour le pool de 1 million de valeurs possibles.

Et il y a d’autres choses comme celle-ci qui sont faciles à négliger. Alors, permettez-moi de le répéter?: ne construisez pas cela à partir de zéro, mais comptez sur les solutions existantes.

Quoi qu'il en soit, j'espère que vous avez appris quelque chose de nouveau aujourd'hui, et que la logique d'OTP ne sera plus un mystère pour vous à partir de maintenant. De plus, si à un moment donné de votre vie, vous devez faire en sorte que votre appareil hors ligne génère des valeurs à l'aide d'un algorithme reproductible, vous avez une bonne idée par où commencer.

Merci pour le temps que vous avez passé à lire cet article et amusez-vous?! =)

P.S. Recevez un e-mail une fois que je publie un nouvel article - abonnez-vous ici

P.P.S. Comme le reste des cool kids, j'ai créé un compte Bluesky récemment, alors, s'il vous pla?t, aidez-moi à rendre mon flux plus amusant =)

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!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefa?on, veuillez contacter admin@php.cn

Outils d'IA chauds

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

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

Quelles sont les implications de la liaison statique de Go par défaut? Quelles sont les implications de la liaison statique de Go par défaut? Jun 19, 2025 am 01:08 AM

GO compile le programme dans un binaire autonome par défaut, la raison principale est la liaison statique. 1. Déploiement plus simple: aucune installation supplémentaire de bibliothèques de dépendances, ne peut être exécutée directement sur les distributions Linux; 2. 3. Prévisibilité et sécurité plus élevées: éviter les risques provoqués par les changements dans les versions externes de la bibliothèque et améliorer la stabilité; 4. Flexibilité de fonctionnement limitée: Impossible de mise à jour à chaud des bibliothèques partagées, et se recompiler et le déploiement sont nécessaires pour corriger les vulnérabilités de dépendance. Ces fonctionnalités sont adaptées aux outils CLI, aux microservices et à d'autres scénarios, mais des compromis sont nécessaires dans les environnements où le stockage est restreint ou repose sur une gestion centralisée.

Comment GO Assure-t-il la sécurité de la mémoire sans gestion manuelle de la mémoire comme en C? Comment GO Assure-t-il la sécurité de la mémoire sans gestion manuelle de la mémoire comme en C? Jun 19, 2025 am 01:11 AM

GoEnsuresMemorySafetywithoutmanual Management ThroughhroughAutomaticGarBageCollection, nopointeraRITHMetic, SafeConcurrency, AndruntimeCkecks.first, Go’sgarBageColEctorAutomAccilmatmestsunusedMemory, empêchant le sanddanglingpoiners.

Comment créer un canal tamponné dans Go? (par exemple, Make (Chan Int, 10)) Comment créer un canal tamponné dans Go? (par exemple, Make (Chan Int, 10)) Jun 20, 2025 am 01:07 AM

Pour créer un canal tampon dans GO, spécifiez simplement les paramètres de capacité dans la fonction de faire. Le canal tampon permet à l'opération d'envoi de stocker temporairement les données en cas de récepteur, tant que la capacité spécifiée n'est pas dépassée. Par exemple, Ch: = Make (Chanint, 10) crée un canal tampon qui peut stocker jusqu'à 10 valeurs entières; Contrairement aux canaux non frappés, les données ne seront pas bloquées immédiatement lors de l'envoi, mais les données seront temporairement stockées dans le tampon jusqu'à ce qu'elles soient enlevées par le récepteur; Lorsque vous l'utilisez, veuillez noter: 1. Le réglage de la capacité doit être raisonnable pour éviter les déchets de mémoire ou le blocage fréquent; 2. Le tampon doit empêcher l'accumulation de problèmes de mémoire indéfiniment dans le tampon; 3. Le signal peut être passé par le type de chantruct {} pour enregistrer les ressources; Les scénarios courants incluent le contr?le du nombre de modèles de concurrence et de consommation producteur et de différenciation

Comment pouvez-vous utiliser GO pour les taches de programmation système? Comment pouvez-vous utiliser GO pour les taches de programmation système? Jun 19, 2025 am 01:10 AM

GO est idéal pour la programmation système car il combine les performances des langages compilés tels que C avec la facilité d'utilisation et la sécurité des langages modernes. 1. En termes d'opérations de fichiers et de répertoires, le package OS de GO prend en charge la création, la suppression, le renommage et la vérification si les fichiers et les répertoires existent. Utilisez OS.Readfile pour lire l'intégralité du fichier dans une ligne de code, qui convient à l'écriture de scripts de sauvegarde ou d'outils de traitement de journal; 2. 3. En termes de réseau et de concurrence, le package net prend en charge la programmation TCP / UDP, la requête DNS et les ensembles originaux.

Comment appeler une méthode sur une instance de structure en Go? Comment appeler une méthode sur une instance de structure en Go? Jun 24, 2025 pm 03:17 PM

Dans le langage GO, l'appel d'une méthode de structure nécessite d'abord de définir la structure et la méthode qui lie le récepteur et l'accès à l'aide d'un numéro de point. Après avoir défini le rectangle de structure, la méthode peut être déclarée via le récepteur de valeur ou le récepteur de pointeur; 1. Utilisez le récepteur de valeur tel que Func (Rrectangle) Area () Int et appelez directement-le via rect.area (); 2. Si vous avez besoin de modifier la structure, utilisez le récepteur de pointeur tel que SetWidth (R * rectangle) de Func (R * R * 3. Lors de l'intégration de la structure, la méthode de structure intégrée sera améliorée et peut être appelée directement par la structure extérieure; 4. GO n'a pas besoin de forcer l'utilisation de Getter / Setter,

Que sont les interfaces en Go et comment les définir? Que sont les interfaces en Go et comment les définir? Jun 22, 2025 pm 03:41 PM

Dans GO, une interface est un type qui définit le comportement sans spécifier l'implémentation. Une interface se compose de signatures de méthode, et tout type qui implémente ces méthodes satisfait automatiquement l'interface. Par exemple, si vous définissez une interface de haut-parleur contenant la méthode Speak (), tous les types qui implémentent la méthode peuvent être considérés comme haut-parleur. Les interfaces conviennent à la rédaction de fonctions communes, aux détails de l'implémentation abstrait et à l'utilisation d'objets simulés dans les tests. La définition d'une interface utilise le mot-clé d'interface et répertorie les signatures de la méthode, sans déclarer explicitement le type pour implémenter l'interface. Les cas d'utilisation courants incluent les journaux, le formatage, les abstractions de différentes bases de données ou services et des systèmes de notification. Par exemple, les types de chiens et de robots peuvent implémenter des méthodes Speak et les transmettre à la même Anno

Comment utiliser les fonctions de cha?ne à partir du package de cha?nes dans Go? (par exemple, Len (), Strings.Contains (), Strings.Index (), Strings.replaceAll ()) Comment utiliser les fonctions de cha?ne à partir du package de cha?nes dans Go? (par exemple, Len (), Strings.Contains (), Strings.Index (), Strings.replaceAll ()) Jun 20, 2025 am 01:06 AM

Dans le langage GO, les opérations de cha?ne sont principalement implémentées via le package des cha?nes et les fonctions intégrées. 1.Strings.Contains () est utilisé pour déterminer si une cha?ne contient une sous-cha?ne et renvoie une valeur booléenne; 2.Strings.Index () peut trouver l'emplacement où la sous-cha?ne appara?t pour la première fois, et s'il n'existe pas, il renvoie -1; 3.Strings.ReplaceALL () peut remplacer toutes les sous-cha?nes correspondantes et peut également contr?ler le nombre de remplacements via des cha?nes.replace (); 4.Len () La fonction est utilisée pour obtenir la longueur des octets de la cha?ne, mais lors du traitement de l'Unicode, vous devez prêter attention à la différence entre les caractères et les octets. Ces fonctions sont souvent utilisées dans des scénarios tels que le filtrage des données, l'analyse de texte et le traitement des cha?nes.

Comment utiliser le package IO pour fonctionner avec des flux d'entrée et de sortie dans GO? Comment utiliser le package IO pour fonctionner avec des flux d'entrée et de sortie dans GO? Jun 20, 2025 am 11:25 AM

ThegoiopackageProvidesInterfacesLikeReaderAndWritertoHandlei / Ooperations UniformlyAcrossources.1.io.Reader'sreadMethoDenablesReadingFromvariousSourcesuchasFilesorHttpResponsses.2.Io.writer'swritethodfacilita

See all articles