Go-Sprache ist eine Programmiersprache, die Parallelität unterstützt, und eine ihrer Kernfunktionen sind Goroutinen. Goroutinen sind leichtgewichtige Threads, die es uns ermöglichen, gleichzeitige Ausführungsprozesse in unseren Programmen zu erstellen. Durch die Verwendung von Goroutinen können wir problemlos effiziente gleichzeitige Programme schreiben. In diesem Artikel erfahren Sie, wie Sie Goroutinen in Go verwenden.
Was sind Goroutinen?
Goroutinen sind leichtgewichtige Threads, die von der Go-Laufzeit verwaltet werden. Im Gegensatz zu Betriebssystem-Threads werden Goroutinen nicht vom Betriebssystemkernel verwaltet, sondern von der Go-Laufzeit unterstützt. Daher sind Goroutinen leichter und das Erstellen und Zerstören von Goroutinen ist schneller als Betriebssystem-Threads. Goroutinen sind der Kern der Parallelität der Go-Sprache und ermöglichen die gleichzeitige Trennung und Ausführung von Funktionskörpern.
So erstellen Sie Goroutinen
In Go können wir das Schlüsselwort go
verwenden, um eine neue Goroutine zu erstellen. Hier ist ein einfaches Beispiel: go
来创建一个新的Goroutine。下面是一个简单的例子:
package main import ( "fmt" "time" ) func hello() { fmt.Println("Hello goroutine!") } func main() { go hello() time.Sleep(1 * time.Second) fmt.Println("main function") }
在这个例子中,我们定义了一个hello
函数,它会在一个新的Goroutine中执行。我们在main
函数中使用关键字go
创建一个新的Goroutine,将hello
函数作为参数传递给它。当我们运行程序时,hello
函数将在一个新的Goroutine中异步运行,而main
函数则会继续执行。我们使用time.Sleep
函数让main
函数等待1秒钟,以确保hello
函数有足够的时间执行。
Goroutines的执行流程
创建Goroutines后,它会和主线程并发执行,Goroutines可以异步地并发执行其他的函数或代码。Go程序会在一个主Goroutine中启动。当我们使用关键字go
创建一个新的Goroutine时,Go runtime会创建一个新的轻量级线程并分配一个Goroutine栈,然后将该Goroutine添加到Go runtime的调度器中。Go runtime会根据调度算法去选择一个可用的Goroutine运行,这些可用Goroutines中可能会有其他Go程序中的Goroutine。如果Go runtime没有发现有可用的Goroutine,那么程序可能会进入休眠状态。
Goroutines的调度
Go runtime使用Go scheduler调度器来调度Goroutines的运行。当我们创建一个新的Goroutine时,它会被添加到调度器的运行队列中。当调度器准备运行Goroutine时,它会从队列中选择一个Goroutine运行,直到该Goroutine阻塞或调用了time.Sleep
等函数。在这种情况下,调度器会暂停该Goroutine的执行,并将它放回到队列中,直到它再次准备好运行。
Goroutines的阻塞
阻塞是指Goroutines无法继续执行的情况。当Goroutine调用了某些会引起阻塞的函数时,该Goroutine会被暂停,直到函数返回结果。这些函数包括:I/O操作,网络请求,系统调用,锁等。如果Goroutine处于阻塞状态,调度器会将该Goroutine放回到队列中,直到它再次准备好运行。
Goroutines的同步
在Go中,我们可以使用通道(Channel)来进行Goroutines之间的同步和通信。通道是一种用于在Goroutines之间传递数据的机制,它可以阻塞Goroutines的运行。以下是一个使用通道进行同步的例子:
package main import ( "fmt" ) func main() { ch := make(chan int) go func() { fmt.Println("Goroutine starts") ch <- 1 }() fmt.Println("Main goroutine waiting") <-ch fmt.Println("Main goroutine exiting") }
在这个例子中,我们首先创建了一个通道ch
,然后在一个新的Goroutine中执行一个函数。在函数中,我们打印了一条消息,并将数字1写入通道。在main
函数中,我们在通道上等待,直到我们收到了一个值。一旦我们收到了值,main
函数将退出。这是一个非常简单的例子,但它演示了如何使用通道在Goroutines之间进行同步。
Goroutines的错误处理
当Goroutine出现错误时,它会崩溃,并抛出一个Panic错误。在一个Goroutine发生错误时,它的错误信息只会被输出到控制台,并且无法访问Goroutine的状态。为了避免程序崩溃,我们可以使用recover函数来恢复Panic错误。以下是一个使用recover函数的例子:
package main import ( "fmt" ) func main() { // define a function to run inside Goroutine goroutineFunc := func() { defer func() { if err := recover(); err != nil { fmt.Println("Error:", err) } }() fmt.Println("Goroutine started") panic("Something went wrong") } // start Goroutine go goroutineFunc() // wait in case Goroutine is not finished yet var input string fmt.Scanln(&input) fmt.Println("End of program") }
在这个例子中,我们首先定义了一个函数goroutineFunc
,它会在一个新的Goroutine中执行。在函数中,我们打印了一条消息,并调用了panic
函数来模拟一个错误。在goroutineFunc
中,我们使用defer
关键字来定义一个函数,该函数用于捕获Panic错误。当我们在goroutineFunc
中执行panic
函数时,它会崩溃并抛出一个Panic错误。由于我们在defer
函数中使用了recover
rrreee
hello
-Funktion, die in einer neuen Goroutine ausgeführt wird. Wir erstellen eine neue Goroutine mit dem Schlüsselwort go
in der Funktion main
und übergeben ihr die Funktion hello
als Parameter. Wenn wir das Programm ausführen, wird die Funktion hello
asynchron in einer neuen Goroutine ausgeführt und die Funktion main
wird weiterhin ausgeführt. Wir verwenden die Funktion time.Sleep
, um die Funktion main
1 Sekunde lang warten zu lassen, um sicherzustellen, dass die Funktion hello
genügend Zeit zum Ausführen hat. Der Ausführungsprozess von Goroutinen#🎜🎜##🎜🎜#Nachdem Goroutinen erstellt wurden, werden sie gleichzeitig mit dem Hauptthread ausgeführt. Goroutinen können andere Funktionen oder Codes asynchron und gleichzeitig ausführen. Go-Programme werden in einer Haupt-Goroutine gestartet. Wenn wir das Schlüsselwort go
verwenden, um eine neue Goroutine zu erstellen, erstellt die Go-Laufzeit einen neuen Lightweight-Thread, weist einen Goroutine-Stack zu und fügt dann die Goroutine dem Scheduler der Go-Laufzeit hinzu. Die Go-Laufzeit wählt basierend auf dem Planungsalgorithmus eine verfügbare Goroutine zur Ausführung aus. Unter diesen verfügbaren Goroutinen können sich auch Goroutinen in anderen Go-Programmen befinden. Wenn die Go-Laufzeit keine verfügbare Goroutine findet, geht das Programm möglicherweise in den Ruhezustand. #🎜🎜##🎜🎜#Planung von Goroutinen#🎜🎜##🎜🎜#Go Runtime verwendet den Go-Scheduler-Scheduler, um die Ausführung von Goroutinen zu planen. Wenn wir eine neue Goroutine erstellen, wird diese zur Ausführungswarteschlange des Planers hinzugefügt. Wenn der Scheduler bereit ist, eine Goroutine auszuführen, wählt er eine Goroutine aus der Warteschlange zur Ausführung aus, bis die Goroutine eine Funktion wie time.Sleep
blockiert oder aufruft. In diesem Fall pausiert der Scheduler die Ausführung der Goroutine und stellt sie wieder in die Warteschlange, bis sie wieder zur Ausführung bereit ist. #🎜🎜##🎜🎜#Blockierung von Goroutinen#🎜🎜##🎜🎜#Blockierung bezieht sich auf die Situation, in der Goroutinen nicht weiter ausgeführt werden können. Wenn eine Goroutine eine Blockierungsfunktion aufruft, wird die Goroutine angehalten, bis die Funktion ein Ergebnis zurückgibt. Zu diesen Funktionen gehören: E/A-Vorgänge, Netzwerkanforderungen, Systemaufrufe, Sperren usw. Wenn eine Goroutine blockiert ist, stellt der Scheduler die Goroutine wieder in die Warteschlange, bis sie wieder laufbereit ist. #🎜🎜##🎜🎜#Synchronisierung von Goroutinen#🎜🎜##🎜🎜#In Go können wir Kanäle (Channel) für die Synchronisierung und Kommunikation zwischen Goroutinen verwenden. Ein Kanal ist ein Mechanismus zum Übertragen von Daten zwischen Goroutinen, der die Ausführung von Goroutinen blockieren kann. Das Folgende ist ein Beispiel für die Verwendung von Kanälen zur Synchronisierung: #🎜🎜#rrreee#🎜🎜#In diesem Beispiel erstellen wir zuerst einen Kanal ch
und führen dann eine Funktion in einer neuen Goroutine aus. In der Funktion haben wir eine Nachricht gedruckt und die Nummer 1 in den Kanal geschrieben. In der Funktion main
warten wir auf dem Kanal, bis wir einen Wert erhalten. Sobald wir den Wert erhalten, wird die Funktion main
beendet. Dies ist ein sehr einfaches Beispiel, aber es zeigt, wie Kanäle zur Synchronisierung zwischen Goroutinen verwendet werden. #🎜🎜##🎜🎜#Fehlerbehandlung von Goroutinen#🎜🎜##🎜🎜#Wenn in einer Goroutine ein Fehler auftritt, stürzt sie ab und löst einen Panikfehler aus. Wenn in einer Goroutine ein Fehler auftritt, wird die Fehlermeldung nur an die Konsole ausgegeben und auf den Status der Goroutine kann nicht zugegriffen werden. Um einen Programmabsturz zu vermeiden, können wir die Wiederherstellungsfunktion verwenden, um Panic-Fehler zu beheben. Das Folgende ist ein Beispiel für die Verwendung der Wiederherstellungsfunktion: #🎜🎜#rrreee#🎜🎜#In diesem Beispiel definieren wir zunächst eine Funktion goroutineFunc
, die in einer neuen Goroutine ausgeführt wird. In der Funktion geben wir eine Nachricht aus und rufen die Funktion panic
auf, um einen Fehler zu simulieren. In goroutineFunc
verwenden wir das Schlüsselwort defer
, um eine Funktion zu definieren, die zum Erfassen von Panic-Fehlern verwendet wird. Wenn wir die Funktion panic
in goroutineFunc
ausführen, stürzt sie ab und löst einen Panic-Fehler aus. Da wir die Funktion recover
in der Funktion defer
verwendet haben, können wir diesen Fehler erfassen und die Fehlermeldung auf der Konsole ausgeben. #🎜🎜##🎜🎜#SCHLUSSFOLGERUNG#🎜🎜#Goroutinen sind eine der Kernfunktionen der Parallelität der Go-Sprache. Sie können parallele Ausführungsprozesse im Programm erstellen und verarbeiten und die Programmleistung verbessern. In diesem Artikel haben wir gelernt, wie man Goroutinen in Go verwendet, einschließlich der Erstellung von Goroutinen, des Ausführungsablaufs von Goroutinen, der Planung, Blockierung, Synchronisierung und Fehlerbehandlung usw. Durch die Verwendung von Goroutinen können wir problemlos effiziente gleichzeitige Programme schreiben.
Das obige ist der detaillierte Inhalt vonWie verwende ich Goroutinen in Go?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!