Qu'est-ce que le report dans Go ? Comment l'utiliser ?
Cet article vous est présenté par la rubrique tutoriel go languageLe sujet porte sur l'apprentissage et l'utilisation de go defer. J'espère qu'il sera utile aux amis dans le besoin !
En Go, un appel de fonction peut suivre un mot-clé defer
pour former un appel de fonction différé. Lorsqu'un appel de fonction est retardé, il ne sera pas exécuté immédiatement. Il sera poussé dans une pile d'appels différés maintenue par la coroutine actuelle. Lorsqu'un appel de fonction (qui peut ou non être un appel différé) revient et entre dans sa phase de sortie, tous les appels différés qui ont été poussés dans cet appel de fonction seront exécutés dans l'ordre inverse de l'ordre dans lequel ils ont été poussés sur la pile. . Lorsque tous ces appels retardés sont exécutés, l’appel de fonction se termine réellement. Un exemple simple :
package mainimport "fmt"func sum(a, b int) { defer fmt.Println("sum函数即将返回") defer fmt.Println("sum函数finished") fmt.Printf("参数a=%v,参数b=%v,两数之和为%v\n", a, b, a+b)}func main() { sum(1, 2)}
参数a=1,参数b=2,两数之和为3 sum函数finished sum函数即将返回
defer
关键字后面,形成一个延迟函数调用。当一个函数调用被延迟后,它不会立即被执行。它将被推入由当前协程维护的一个延迟调用堆栈。 当一个函数调用(可能是也可能不是一个延迟调用)返回并进入它的退出阶段后,所有在此函数调用中已经被推入的延迟调用将被按照它们被推入堆栈的顺序逆序执行。 当所有这些延迟调用执行完毕后,此函数调用也就真正退出了。
举个简单的例子:
package mainimport "fmt"func Print(a int) {fmt.Println("defer函数中a的值=", a)}func main() {a := 10defer Print(a)a = 1000fmt.Println("a的值=", a)}
output:
a的值= 1000 defer函数中a的值= 10
事实上,每个协程维护着两个调用堆栈。
- 一个是正常的函数调用堆栈。在此堆栈中,相邻的两个调用存在着调用关系。晚进入堆栈的调用被早进入堆栈的调用所调用。 此堆栈中最早被推入的调用是对应协程的启动调用。
- 另一个堆栈是上面提到的延迟调用堆栈。处于延迟调用堆栈中的任意两个调用之间不存在调用关系。
defer函数参数估值
- 对于一个延迟函数调用,它的实参是在此调用被推入延迟调用堆栈的时候被估值的。
- 一个匿名函数体内的表达式是在此函数被执行的时候才会被逐个估值的,不管此函数是被普通调用还是延迟调用。
例子1:
package mainimport "fmt"func main() { func() { for i := 0; i < 3; i++ { defer fmt.Println("a=", i) } }() fmt.Println() func() { for i := 0; i < 3; i++ { defer func() { fmt.Println("b=", i) }() } }()}
output:
a= 2 a= 1 a= 0 b= 3 b= 3 b= 3
defer Print(a) 被加入到延迟调用堆栈的时候,a 的值是5,故defer Print(a) 输出的结果为5
例子2:
package mainimport "fmt"func main() { func() { for i := 0; i < 3; i++ { defer fmt.Println("a=", i) } }() fmt.Println() func() { for i := 0; i < 3; i++ { defer func(i int) { fmt.Println("b=", i) }(i) } }()}
output:
a= 2 a= 1 a= 0 b= 2 b= 1 b= 0
第一个匿名函数循环中的 i 是在 fmt.Println函数调用被推入延迟调用堆栈的时候估的值,因此输出结果是 2,1,0 , 第二个匿名函数中的 i 是匿名函数调用退出阶段估的值(此时 i 已经变成3了),故结果输出:3,3,3。
其实对第二个匿名函数调用略加修改,就能使它输出和匿名函数一相同的结果:
package mainimport ( "fmt" "time")func p(a, b int) int { return a / b}func main() { go func() { fmt.Println(p(1, 0)) }() time.Sleep(time.Second) fmt.Println("程序正常退出~~~")}
output:
panic: runtime error: integer pide by zero goroutine 6 [running]: main.p(...) /Users/didi/Desktop/golang/defer.go:9 main.main.func1() /Users/didi/Desktop/golang/defer.go:14 +0x12 created by main.main /Users/didi/Desktop/golang/defer.go:13 +0x39exit status 2
恐慌(panic)和恢复(defer + recover)
Go不支持异常抛出和捕获,而是推荐使用返回值显式返回错误。 不过,Go支持一套和异常抛出/捕获类似的机制。此机制称为恐慌/恢复(panic/recover)机制。
我们可以调用内置函数panic
来产生一个恐慌以使当前协程进入恐慌状况。
进入恐慌状况是另一种使当前函数调用开始返回的途径。 一旦一个函数调用产生一个恐慌,此函数调用将立即进入它的退出阶段,在此函数调用中被推入堆栈的延迟调用将按照它们被推入的顺序逆序执行。
通过在一个延迟函数调用之中调用内置函数recover
En fait, chaque coroutine maintient deux piles d'appels.
- L'une est la pile d'appels de fonction normale. Dans cette pile, deux appels adjacents ont une relation d'appel. Les appels placés tardivement sur la pile sont appelés par les appels placés tôt sur la pile. Le premier appel poussé dans cette pile est l'appel de démarrage de la coroutine correspondante.
- Une autre pile est la pile d'appels différés mentionnée ci-dessus. Il n'existe aucune relation d'appel entre deux appels dans la pile d'appels différés.
- Pour un appel de fonction différé, ses paramètres réels sont évalués lorsque l'appel est poussé dans la pile d'appels différés de.
- Les expressions dans le corps d'une fonction anonyme seront évaluées une par une lors de l'exécution de la fonction, que la fonction soit appelée normalement ou retardée. Exemple 1 :
package mainimport ( "fmt" "time")func p(a, b int) int { return a / b}func main() { go func() { defer func() { v := recover() if v != nil { fmt.Println("恐慌被恢复了:", v) } }() fmt.Println(p(1, 0)) }() time.Sleep(time.Second) fmt.Println("程序正常退出~~~")}
output:
恐慌被恢复了: runtime error: integer pide by zero 程序正常退出~~~
defer Print(a) est ajouté à la pile d'appels différés, la valeur de a est 5, donc le résultat de sortie de defer Print(a) est 5 Exemple 2 :rrreeeoutput:rrreeei dans la première boucle de fonction anonyme est la valeur estimée lorsque l'appel de la fonction fmt.Println est poussé dans la pile d'appels retardés, donc le résultat de sortie est 2, 1, 0, Le i dans la deuxième fonction anonyme est la valeur estimée pendant la phase de sortie de l'appel de fonction anonyme (i est devenu 3 à ce moment), donc le résultat est : 3, 3, 3. En fait, avec une légère modification du deuxième appel de fonction anonyme, il peut afficher le même résultat que celui de la fonction anonyme :
rrreee
panic
pour générer une panique afin de mettre la coroutine actuelle dans un état de panique. 🎜🎜Entrer dans une condition de panique est une autre façon pour l'appel de fonction en cours de commencer à revenir. Une fois qu'un appel de fonction génère une panique, l'appel de fonction entrera immédiatement dans sa phase de sortie et les appels différés poussés sur la pile au sein de l'appel de fonction seront exécutés dans l'ordre inverse de l'ordre dans lequel ils ont été poussés. 🎜🎜En appelant la fonction intégrée recover
dans un appel de fonction retardé, une panique dans la coroutine actuelle peut être éliminée, permettant à la coroutine actuelle de rentrer dans des conditions normales. 🎜🎜Avant qu'une coroutine paniquée ne sorte, la panique ne se propagera pas aux autres coroutines. Si une coroutine se termine dans un état de panique, elle fera planter tout le programme. Regardez les deux exemples suivants : 🎜rrreee🎜output:🎜rrreee🎜p fonction panique (le diviseur est 0), car la coroutine n'a pas de mécanisme de récupération de panique, provoquant le crash de l'ensemble du programme. 🎜Si la coroutine où se trouve la fonction p est ajoutée avec une récupération de panique (différer + récupérer), le programme peut se terminer normalement. 🎜rrreee🎜sortie :🎜rrreee🎜🎜Pour plus de connaissances sur le golang, veuillez visiter la colonne 🎜🎜golang🎜🎜tutoriel 🎜 !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!

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

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

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

Sujets chauds





Lire et écrire des fichiers en toute sécurité dans Go est crucial. Les directives incluent : Vérification des autorisations de fichiers Fermeture de fichiers à l'aide de reports Validation des chemins de fichiers Utilisation de délais d'attente contextuels Le respect de ces directives garantit la sécurité de vos données et la robustesse de vos applications.

Comment configurer le pool de connexions pour les connexions à la base de données Go ? Utilisez le type DB dans le package base de données/sql pour créer une connexion à la base de données ; définissez MaxOpenConns pour contrôler le nombre maximum de connexions simultanées ; définissez MaxIdleConns pour définir le nombre maximum de connexions inactives ; définissez ConnMaxLifetime pour contrôler le cycle de vie maximum de la connexion ;

La différence entre le framework GoLang et le framework Go se reflète dans l'architecture interne et les fonctionnalités externes. Le framework GoLang est basé sur la bibliothèque standard Go et étend ses fonctionnalités, tandis que le framework Go se compose de bibliothèques indépendantes pour atteindre des objectifs spécifiques. Le framework GoLang est plus flexible et le framework Go est plus facile à utiliser. Le framework GoLang présente un léger avantage en termes de performances et le framework Go est plus évolutif. Cas : gin-gonic (framework Go) est utilisé pour créer l'API REST, tandis qu'Echo (framework GoLang) est utilisé pour créer des applications Web.

Les données JSON peuvent être enregistrées dans une base de données MySQL à l'aide de la bibliothèque gjson ou de la fonction json.Unmarshal. La bibliothèque gjson fournit des méthodes pratiques pour analyser les champs JSON, et la fonction json.Unmarshal nécessite un pointeur de type cible pour désorganiser les données JSON. Les deux méthodes nécessitent la préparation d'instructions SQL et l'exécution d'opérations d'insertion pour conserver les données dans la base de données.

La fonction FindStringSubmatch recherche la première sous-chaîne correspondant à une expression régulière : la fonction renvoie une tranche contenant la sous-chaîne correspondante, le premier élément étant la chaîne entière correspondante et les éléments suivants étant des sous-chaînes individuelles. Exemple de code : regexp.FindStringSubmatch(text,pattern) renvoie une tranche de sous-chaînes correspondantes. Cas pratique : Il peut être utilisé pour faire correspondre le nom de domaine dans l'adresse email, par exemple : email:="user@example.com", pattern:=@([^\s]+)$ pour obtenir la correspondance du nom de domaine [1].

Chemin d'apprentissage du backend: le parcours d'exploration du front-end à l'arrière-end en tant que débutant back-end qui se transforme du développement frontal, vous avez déjà la base de Nodejs, ...

L'utilisation de fuseaux horaires prédéfinis dans Go comprend les étapes suivantes : Importez le package « time ». Chargez un fuseau horaire spécifique via la fonction LoadLocation. Utilisez le fuseau horaire chargé dans des opérations telles que la création d'objets Time, l'analyse de chaînes horaires et l'exécution de conversions de date et d'heure. Comparez les dates en utilisant différents fuseaux horaires pour illustrer l'application de la fonctionnalité de fuseau horaire prédéfini.

FAQ sur le développement du framework Go : Sélection du framework : Dépend des exigences de l'application et des préférences du développeur, telles que Gin (API), Echo (extensible), Beego (ORM), Iris (performance). Installation et utilisation : Utilisez la commande gomod pour installer, importer le framework et l'utiliser. Interaction avec la base de données : utilisez les bibliothèques ORM, telles que gorm, pour établir des connexions et des opérations avec la base de données. Authentification et autorisation : utilisez un middleware de gestion de session et d'authentification tel que gin-contrib/sessions. Cas pratique : utilisez le framework Gin pour créer une API de blog simple qui fournit des fonctions POST, GET et autres.
