Heim Backend-Entwicklung Golang Was ist die Anweisung zur verzögerten Ausführung in der Go-Sprache?

Was ist die Anweisung zur verzögerten Ausführung in der Go-Sprache?

Jan 11, 2023 pm 06:28 PM
golang go语言 defer

In der Go-Sprache ist die Anweisung zur verzögerten Ausführung die Defer-Anweisung und die Syntax lautet „jede Anweisung verzögern“. Die Defer-Anweisung verzögert die Verarbeitung der darauf folgenden Anweisungen. Wenn die Funktion, zu der die Defer-Anweisung gehört, zurückkehrt, werden die verzögerten Anweisungen in der umgekehrten Reihenfolge der Defer-Anweisung ausgeführt wird zuletzt ausgeführt, und die zuletzt aufgeschobene Anweisung wird zuerst ausgeführt.

Was ist die Anweisung zur verzögerten Ausführung in der Go-Sprache?

Die Betriebsumgebung dieses Tutorials: Windows 7-System, GO Version 1.18, Dell G3-Computer.

Anweisung zur verzögerten Ausführung (Defer-Anweisung) in der Go-Sprache

Es gibt eine Anweisung zur verzögerten Ausführung in der Go-Sprache, die durch das Schlüsselwort defer identifiziert wird.

Das Schlüsselwort defer verzögert die Verarbeitung der darauf folgenden Anweisungen. Wenn die Funktion, zu der defer gehört, zurückkehrt, werden die verzögerten Verarbeitungsanweisungen in der umgekehrten Reihenfolge von defer ausgeführt wird zuletzt ausgeführt. Die zuletzt zurückgestellte Anweisung wird zuerst ausgeführt.

Das Format ist wie folgt:

defer 任意语句
Nach dem Login kopieren

Die Anweisungen nach defer werden nicht sofort ausgeführt. Wenn die Funktion, zu der defer gehört, zurückkehrt, werden alle defer-Anweisungen im Funktionskörper in umgekehrter Reihenfolge ausgeführt Aussehen, das heißt, die letzte Anweisung im Funktionskörper Eine Defer-Anweisung wird zuerst ausgeführt.

package main

import "fmt"

func main(){
	fmt.Println("start now")
	defer fmt.Println("这是第一句defer语句")
	defer fmt.Println("这是第二句defer语句")
	defer fmt.Println("这是第三句defer语句")
	fmt.Println("end")
}
Nach dem Login kopieren

Das Ausführungsergebnis lautet wie folgt:

start now
end
这是第三句defer语句
这是第二句defer语句
这是第一句defer语句
Nach dem Login kopieren

Da die Defer-Anweisung aufgerufen wird, wenn die aktuelle Funktion kurz vor der Rückkehr steht, wird Defer häufig zum Freigeben von Ressourcen verwendet.

Die Verarbeitungsreihenfolge mehrerer verzögerter Ausführungsanweisungen

Wenn mehrere Verzögerungsverhalten registriert werden, werden sie in umgekehrter Reihenfolge ausgeführt (ähnlich einem Stapel, d. h. der letzte Eingang, der erste Ausgang). Der folgende Code druckt eine Reihe numerischer Anweisungen verzögern die Verarbeitung in der Reihenfolge wie folgt:

package main
import (
    "fmt"
)
func main() {
    fmt.Println("defer begin")
    // 将defer放入延迟调用栈
    defer fmt.Println(1)
    defer fmt.Println(2)
    // 最后一个放入, 位于栈顶, 最先调用
    defer fmt.Println(3)
    fmt.Println("defer end")
}
Nach dem Login kopieren

Die Codeausgabe lautet wie folgt:

defer begin
defer end
3
2
1
Nach dem Login kopieren

Die Ergebnisanalyse lautet wie folgt:

  • Die Verzögerungsreihenfolge des Codes ist gegenüber der endgültigen Ausführungsreihenfolge umgekehrt.

  • Der verzögerte Aufruf erfolgt, wenn die Funktion endet, in der sich defer befindet. Das Ende der Funktion kann sein, wenn sie normal zurückkehrt oder wenn eine Ausfallzeit auftritt.

Verwenden Sie verzögerte Ausführungsanweisungen, um Ressourcen freizugeben, wenn die Funktion beendet wird.

Die Verarbeitung gepaarter Vorgänge im Geschäfts- oder Logikbereich ist relativ umständlich, z. B. das Öffnen und Schließen von Dateien, das Empfangen und Beantworten von Anfragen sowie das Sperren und Entsperren usw. Unter diesen Vorgängen wird am häufigsten das korrekte Freigeben und Schließen von Ressourcen bei jedem Funktionsausgang übersehen.

Die Defer-Anweisung ist genau die Anweisung, die ausgeführt wird, wenn die Funktion beendet wird. Daher kann die Verwendung von Defer Probleme mit der Ressourcenfreigabe sehr bequem lösen.

1) Verzögertes gleichzeitiges Entsperren verwenden

Im folgenden Beispiel wird die Karte gleichzeitig in der Funktion verwendet. Zur Vermeidung von Race Conditions wird sync.Mutex zum Sperren verwendet:

var (
    // 一个演示用的映射
    valueByKey      = make(map[string]int)
    // 保证使用映射时的并发安全的互斥锁
    valueByKeyGuard sync.Mutex
)
// 根据键读取值
func readValue(key string) int {
    // 对共享资源加锁
    valueByKeyGuard.Lock()
    // 取值
    v := valueByKey[key]
    // 对共享资源解锁
    valueByKeyGuard.Unlock()
    // 返回值
    return v
}
Nach dem Login kopieren

Die Codebeschreibung lautet folgt:

  • Zeile 3, Instanziieren einer Karte, der Schlüssel ist vom Typ String und der Wert ist int.

  • Zeile 5: Die Karte ist standardmäßig nicht parallelitätssicher. Bereiten Sie einen sync.Mutex-Mutex vor, um den Kartenzugriff zu schützen.

  • Zeile 9: Die Funktion readValue() gibt einen Schlüssel aus und gibt den Wert zurück, nachdem sie den Wert aus der Karte abgerufen hat. Diese Funktion wird in einer gleichzeitigen Umgebung verwendet und muss die Sicherheit der Parallelität gewährleisten.

  • Zeile 11, Mutex zum Sperren verwenden.

  • Zeile 13, holen Sie sich den Wert aus der Karte.

  • Zeile 15, Entsperren mit Mutex.

  • Zeile 17 gibt den erhaltenen Kartenwert zurück.

Verwenden Sie die Defer-Anweisung, um die obige Anweisung zu vereinfachen. Weitere Informationen finden Sie im folgenden Code.

func readValue(key string) int {
    valueByKeyGuard.Lock()
   
    // defer后面的语句不会马上调用, 而是延迟到函数结束时调用
    defer valueByKeyGuard.Unlock()
    return valueByKey[key]
}
Nach dem Login kopieren

Die Zeilen 6 bis 8 des obigen Codes sind Modifikationen und Ergänzungen zum vorherigen Code. Die Codebeschreibung lautet wie folgt:

  • Zeile 6 verwendet die Defer-Anweisung, um das Entsperren nach dem Sperren des Mutex hinzuzufügen wird nicht sofort ausgeführt, sondern wird ausgeführt, wenn die Funktion readValue() zurückkehrt.

  • Zeile 8: Der Vorgang zum Abfragen und Zurückgeben des Werts aus der Karte ist derselbe wie beim Schreiben ohne Verwendung eines Mutex. Im Vergleich zum obigen Code ist dieser Schreibvorgang einfacher.

2) Die Verwendung des Dateihandles mit verzögerter Freigabe

Dateivorgänge erfordern mehrere Prozesse: Öffnen der Datei, Abrufen und Betreiben von Dateiressourcen und Schließen der Ressourcen. Wenn die Dateiressourcen nach Abschluss des Vorgangs nicht geschlossen werden, wird der Vorgang ausgeführt Da die Dateiressourcen niemals freigegeben werden können, wird im folgenden Beispiel eine Funktion zum Abrufen der Dateigröße basierend auf dem Dateinamen implementiert. Die Funktion erfordert Vorgänge wie das Öffnen der Datei, das Abrufen der Dateigröße und das Schließen der Datei . Da jede Systemoperation eine Fehlerbehandlung erfordert, führt jeder Verarbeitungsschritt zu einem Fehler. Beim Beenden müssen daher Ressourcen freigegeben werden, und wir müssen beim Beenden der Funktion genau darauf achten, dass die Dateiressourcen korrekt freigegeben werden folgender Code:

// 根据文件名查询其大小
func fileSize(filename string) int64 {
    // 根据文件名打开文件, 返回文件句柄和错误
    f, err := os.Open(filename)
    // 如果打开时发生错误, 返回文件大小为0
    if err != nil {
        return 0
    }
    // 取文件状态信息
    info, err := f.Stat()
   
    // 如果获取信息时发生错误, 关闭文件并返回文件大小为0
    if err != nil {
        f.Close()
        return 0
    }
    // 取文件大小
    size := info.Size()
    // 关闭文件
    f.Close()
   
    // 返回文件大小
    return size
}
Nach dem Login kopieren

Die Codebeschreibung lautet wie folgt:

  • Zeile 2, Funktion zur Erfassung der Dateigröße definieren, der Rückgabewert ist der 64-Bit-Dateigrößenwert.

  • Zeile 5: Verwenden Sie die vom Betriebssystempaket bereitgestellte Funktion Open (), um eine Datei basierend auf dem angegebenen Dateinamen zu öffnen, und geben Sie das zum Ausführen der Datei verwendete Handle und den Betriebsfehler zurück.

  • Zeile 8: Wenn während des Öffnungsvorgangs ein Fehler auftritt, z. B. wenn die Datei nicht gefunden wird, die Datei belegt ist usw., wird die Dateigröße als 0 zurückgegeben.

  • 第 13 行,此时文件句柄 f 可以正常使用,使用 f 的方法 Stat() 来获取文件的信息,获取信息时,可能也会发生错误。

  • 第 16~19 行对错误进行处理,此时文件是正常打开的,为了释放资源,必须要调用 f 的 Close() 方法来关闭文件,否则会发生资源泄露。

  • 第 22 行,获取文件大小。

  • 第 25 行,关闭文件、释放资源。

  • 第 28 行,返回获取到的文件大小。

在上面的例子中,第 25 行是对文件的关闭操作,下面使用 defer 对代码进行简化,代码如下:

func fileSize(filename string) int64 {
    f, err := os.Open(filename)
    if err != nil {
        return 0
    }
    // 延迟调用Close, 此时Close不会被调用
    defer f.Close()
    info, err := f.Stat()
    if err != nil {
        // defer机制触发, 调用Close关闭文件
        return 0
    }
    size := info.Size()
    // defer机制触发, 调用Close关闭文件
    return size
}
Nach dem Login kopieren

代码中加粗部分为对比前面代码而修改的部分,代码说明如下:

  • 第 10 行,在文件正常打开后,使用 defer,将 f.Close() 延迟调用,注意,不能将这一句代码放在第 4 行空行处,一旦文件打开错误,f 将为空,在延迟语句触发时,将触发宕机错误。

  • 第 16 行和第 22 行,defer 后的语句(f.Close())将会在函数返回前被调用,自动释放资源。

【相关推荐:Go视频教程编程教学

Das obige ist der detaillierte Inhalt vonWas ist die Anweisung zur verzögerten Ausführung in der Go-Sprache?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat -Befehle und wie man sie benutzt
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Was ist das Problem mit Warteschlangen -Thread in Go's Crawler Colly? Was ist das Problem mit Warteschlangen -Thread in Go's Crawler Colly? Apr 02, 2025 pm 02:09 PM

Das Problem der Warteschlange Threading In Go Crawler Colly untersucht das Problem der Verwendung der Colly Crawler Library in Go -Sprache. Entwickler stoßen häufig auf Probleme mit Threads und Anfordern von Warteschlangen. � ...

Welche Bibliotheken werden für die Operationen der schwimmenden Punktzahl in Go verwendet? Welche Bibliotheken werden für die Operationen der schwimmenden Punktzahl in Go verwendet? Apr 02, 2025 pm 02:06 PM

In der Bibliothek, die für den Betrieb der Schwimmpunktnummer in der GO-Sprache verwendet wird, wird die Genauigkeit sichergestellt, wie die Genauigkeit ...

Was soll ich tun, wenn die benutzerdefinierten Strukturbezeichnungen in Goland nicht angezeigt werden? Was soll ich tun, wenn die benutzerdefinierten Strukturbezeichnungen in Goland nicht angezeigt werden? Apr 02, 2025 pm 05:09 PM

Was soll ich tun, wenn die benutzerdefinierten Strukturbezeichnungen in Goland nicht angezeigt werden? Bei der Verwendung von Goland für GO -Sprachentwicklung begegnen viele Entwickler benutzerdefinierte Struktur -Tags ...

Warum hat das Drucken von Saiten mit Println und String () -Funktionen unterschiedliche Effekte? Warum hat das Drucken von Saiten mit Println und String () -Funktionen unterschiedliche Effekte? Apr 02, 2025 pm 02:03 PM

Der Unterschied zwischen Stringdruck in GO -Sprache: Der Unterschied in der Wirkung der Verwendung von Println und String () ist in Go ...

Welche Bibliotheken in GO werden von großen Unternehmen entwickelt oder von bekannten Open-Source-Projekten bereitgestellt? Welche Bibliotheken in GO werden von großen Unternehmen entwickelt oder von bekannten Open-Source-Projekten bereitgestellt? Apr 02, 2025 pm 04:12 PM

Welche Bibliotheken in GO werden von großen Unternehmen oder bekannten Open-Source-Projekten entwickelt? Bei der Programmierung in Go begegnen Entwickler häufig auf einige häufige Bedürfnisse, ...

Wie löste ich das Problem des Typs des user_id -Typs bei der Verwendung von Redis -Stream, um Nachrichtenwarteschlangen in GO -Sprache zu implementieren? Wie löste ich das Problem des Typs des user_id -Typs bei der Verwendung von Redis -Stream, um Nachrichtenwarteschlangen in GO -Sprache zu implementieren? Apr 02, 2025 pm 04:54 PM

Das Problem der Verwendung von RETISTREAM zur Implementierung von Nachrichtenwarteschlangen in der GO -Sprache besteht darin, die Go -Sprache und Redis zu verwenden ...

Was ist der Unterschied zwischen 'var' und 'Typ' Typenwort Definition in der GO -Sprache? Was ist der Unterschied zwischen 'var' und 'Typ' Typenwort Definition in der GO -Sprache? Apr 02, 2025 pm 12:57 PM

Zwei Möglichkeiten, Strukturen in der GO -Sprache zu definieren: Der Unterschied zwischen VAR- und Typ -Schlüsselwörtern. Bei der Definition von Strukturen sieht die Sprache oft zwei verschiedene Schreibweisen: Erstens ...

Wie kann sichergestellt werden, dass die Parallelität beim Schreiben von Multi-Process-Protokollen sicher und effizient ist? Wie kann sichergestellt werden, dass die Parallelität beim Schreiben von Multi-Process-Protokollen sicher und effizient ist? Apr 02, 2025 pm 03:51 PM

Effizient behandeln Probleme mit der Parallelitätssicherheit beim Schreiben von Multi-Process-Protokoll. Mehrere Prozesse schreiben gleichzeitig die gleiche Protokolldatei. Wie kann die Parallelität sicher und effizient sichergestellt werden? Das ist ein ...

See all articles