{"id":294,"date":"2024-09-18T15:53:50","date_gmt":"2024-09-18T08:53:50","guid":{"rendered":"https:\/\/gotutorial.org\/?page_id=294"},"modified":"2024-09-23T15:42:35","modified_gmt":"2024-09-23T08:42:35","slug":"goroutines","status":"publish","type":"page","link":"https:\/\/www.gotutorial.org\/go-tutorial\/goroutines\/","title":{"rendered":"Goroutines"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you will learn how to use goroutines to develop concurrent applications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Processes and Threads<\/h2>\n\n\n\n<p>When you launch a Go Program, the operating system (OS) creates a new <em>process<\/em>. A process is a container that holds program resources, including memory and <em>threads<\/em>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"715\" height=\"249\" src=\"https:\/\/gotutorial.org\/wp-content\/uploads\/2024\/09\/process.png\" alt=\"Simplified version of Process\" class=\"wp-image-319\" style=\"object-fit:cover\" srcset=\"https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/process.png 715w, https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/process-300x104.png 300w\" sizes=\"auto, (max-width: 715px) 100vw, 715px\" \/><\/figure>\n\n\n\n<p>Each process contains at least one thread known as the <em>main thread<\/em>. The main thread is the entry point for the application. When the main thread terminates, the application exits.<\/p>\n\n\n\n<p>When a program has a single thread, it is called a single-threaded program. A process may contain multiple threads. In this case, the program is known as a <em>multi-threaded program<\/em>.<\/p>\n\n\n\n<p>To execute multiple threads, the OS uses a scheduler to schedule the threads to run:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"348\" height=\"584\" src=\"https:\/\/gotutorial.org\/wp-content\/uploads\/2024\/09\/threads.png\" alt=\"Threads\" class=\"wp-image-320\" style=\"width:200px\" srcset=\"https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/threads.png 348w, https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/threads-179x300.png 179w\" sizes=\"auto, (max-width: 348px) 100vw, 348px\" \/><\/figure>\n\n\n\n<p>If the computer has a single CPU, the scheduler switches between threads so fast that often gives us an <em>illusion <\/em>that they are running <em>simultaneously<\/em>. This is called <em>concurrency<\/em>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Concurrency<\/h2>\n\n\n\n<p>Concurrency is about to <em>deal with multiple tasks at the same time<\/em>. It doesn&#8217;t necessarily mean the tasks are running at the same time:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"464\" height=\"93\" src=\"https:\/\/gotutorial.org\/wp-content\/uploads\/2024\/09\/concurrency.png\" alt=\"\" class=\"wp-image-335\" srcset=\"https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/concurrency.png 464w, https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/concurrency-300x60.png 300w\" sizes=\"auto, (max-width: 464px) 100vw, 464px\" \/><\/figure>\n\n\n\n<p>On the other hand, <em>parallelism<\/em> is about executing multiple tasks at the same time. This requires multiple processors or cores.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/gotutorial.org\/wp-content\/uploads\/2024\/09\/parallelism.png\" alt=\"Parallelism\" class=\"wp-image-325\" style=\"object-fit:cover\"\/><\/figure>\n\n\n\n<p>Nowadays, computers have more than one core. Therefore, the OS scheduler can run multiple threads at the same time, which creates a true parallelism:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"340\" height=\"485\" src=\"https:\/\/gotutorial.org\/wp-content\/uploads\/2024\/09\/multicores.png\" alt=\"\" class=\"wp-image-318\" style=\"width:250px\" srcset=\"https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/multicores.png 340w, https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/multicores-210x300.png 210w\" sizes=\"auto, (max-width: 340px) 100vw, 340px\" \/><\/figure>\n\n\n\n<p>To achieve concurrency, other programming languages such as C# or Java use multi-threading. However, developing multi-threaded programs is hard because we need to synchronize between threads carefully or they will break. <\/p>\n\n\n\n<p>To make concurrency easy, Go provides a built-in language feature called <em>goroutines<\/em>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Goroutines<\/h2>\n\n\n\n<p>Goroutines are much lighter than OS threads. They are known as lightweight threads and are managed by the <em>Go runtime scheduler<\/em>.<\/p>\n\n\n\n<p class=\"note\">A lightweight thread does not like an operating system (OS) thread. It uses less memory than the OS thread. One OS thread may include multiple lightweight threads.<\/p>\n\n\n\n<p>The Go runtime scheduler is sitting on top of the OS layer and is in charge of managing the execution of goroutines:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"334\" height=\"712\" src=\"https:\/\/gotutorial.org\/wp-content\/uploads\/2024\/09\/goroutines.png\" alt=\"goroutines\" class=\"wp-image-317\" style=\"width:300px\" srcset=\"https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/goroutines.png 334w, https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/goroutines-141x300.png 141w\" sizes=\"auto, (max-width: 334px) 100vw, 334px\" \/><\/figure>\n\n\n\n<p>The Go runtime scheduler allows goroutines to run concurrently on a single logical processor or in parallel on multiple logical processors. This enables efficient use of system resources and improves performance.<\/p>\n\n\n\n<p>The Go runtime scheduler is designed to handle tens or even hundreds of thousands of goroutines efficiently, making Go well-suited for highly concurrent applications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sequential programs<\/h2>\n\n\n\n<p>Typically, a Go program executes code in sequence line by line from top to bottom. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">package<\/span> main\n\n<span class=\"hljs-keyword\">import<\/span> (\n    <span class=\"hljs-string\">\"fmt\"<\/span>\n    <span class=\"hljs-string\">\"time\"<\/span>\n)\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">task<\/span><span class=\"hljs-params\">(name <span class=\"hljs-keyword\">string<\/span>)<\/span><\/span> {\n    fmt.Println(name, <span class=\"hljs-string\">\"started...\"<\/span>)\n    time.Sleep(<span class=\"hljs-number\">1<\/span> * time.Second)\n    fmt.Println(name, <span class=\"hljs-string\">\"finished\"<\/span>)\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n    <span class=\"hljs-comment\">\/\/ measure the execution time<\/span>\n    start := time.Now()\n    <span class=\"hljs-keyword\">defer<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n        elapsed := time.Since(start)\n        fmt.Printf(<span class=\"hljs-string\">\"It took %d ms\\n\"<\/span>, elapsed.Milliseconds())\n    }()\n\n    task(<span class=\"hljs-string\">\"Task 1\"<\/span>)\n    task(<span class=\"hljs-string\">\"Task 2\"<\/span>)\n    task(<span class=\"hljs-string\">\"Task 3\"<\/span>)\n\n    fmt.Println(<span class=\"hljs-string\">\"Done\"<\/span>)\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, define a function <code>task()<\/code> that takes 1 second to finish:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">task<\/span><span class=\"hljs-params\">(name <span class=\"hljs-keyword\">string<\/span>)<\/span><\/span> {\n    fmt.Println(name, <span class=\"hljs-string\">\"started...\"<\/span>)\n    time.Sleep(<span class=\"hljs-number\">1<\/span> * time.Second)\n    fmt.Println(name, <span class=\"hljs-string\">\"finished\"<\/span>)\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>task()<\/code> function uses the <code>Sleep()<\/code> function from the <code>time<\/code> module to pause the execution for one second. <\/p>\n\n\n\n<p class=\"note\">In real-world applications, the <code>task()<\/code> function may call an external API or make a database connection instead of using the <code>Sleep()<\/code> function.<\/p>\n\n\n\n<p>Second, measure the execution time of the <code>main()<\/code> function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">start := time.Now()\n<span class=\"hljs-keyword\">defer<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n    elapsed := time.Since(start)\n    fmt.Printf(<span class=\"hljs-string\">\"It took %d ms\\n\"<\/span>, elapsed.Milliseconds())\n}()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, call the <code>task()<\/code> function three times with different string arguments:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">task(<span class=\"hljs-string\">\"Task 1\"<\/span>)\ntask(<span class=\"hljs-string\">\"Task 2\"<\/span>)\ntask(<span class=\"hljs-string\">\"Task 3\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Finally, display the <code>Done<\/code> message:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">fmt.Println(<span class=\"hljs-string\">\"Done\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">Task <span class=\"hljs-number\">1<\/span> started...\nTask <span class=\"hljs-number\">1<\/span> finished\nTask <span class=\"hljs-number\">2<\/span> started...\nTask <span class=\"hljs-number\">2<\/span> finished\nTask <span class=\"hljs-number\">3<\/span> started...\nTask <span class=\"hljs-number\">3<\/span> finished\nDone\nIt took <span class=\"hljs-number\">3002<\/span> ms<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The output shows two important pieces of information:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The tasks started and finished in sequence.<\/li>\n\n\n\n<li>Each task function call took one second to finish. Since we called the <code>task()<\/code> function three times, the whole program took about 3 seconds to complete.<\/li>\n<\/ul>\n\n\n\n<p>To speed up the program, we can use goroutines to run the <code>task<\/code> function concurrently.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating Goroutines<\/h2>\n\n\n\n<p>To start a goroutine, you use the <code>go<\/code> keyword followed by a function call that you want to run in a concurrently:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">go<\/span> fn()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>go<\/code> keyword instructs the Go runtime scheduler to spawn a new lightweight thread and run the <code>fn()<\/code> function.<\/p>\n\n\n\n<p>For example, we can use goroutines to run the <code>task<\/code> function concurrently as follows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">package<\/span> main\n\n<span class=\"hljs-keyword\">import<\/span> (\n    <span class=\"hljs-string\">\"fmt\"<\/span>\n    <span class=\"hljs-string\">\"time\"<\/span>\n)\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">task<\/span><span class=\"hljs-params\">(name <span class=\"hljs-keyword\">string<\/span>)<\/span><\/span> {\n    fmt.Println(name, <span class=\"hljs-string\">\"started...\"<\/span>)\n    time.Sleep(<span class=\"hljs-number\">1<\/span> * time.Second)\n    fmt.Println(name, <span class=\"hljs-string\">\"finished\"<\/span>)\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n    <span class=\"hljs-comment\">\/\/ measure the execution time<\/span>\n    start := time.Now()\n    <span class=\"hljs-keyword\">defer<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n        elapsed := time.Since(start)\n        fmt.Printf(<span class=\"hljs-string\">\"It took %d ms\\n\"<\/span>, elapsed.Milliseconds())\n    }()\n\n    <span class=\"hljs-keyword\">go<\/span> task(<span class=\"hljs-string\">\"Task 1\"<\/span>)\n    <span class=\"hljs-keyword\">go<\/span> task(<span class=\"hljs-string\">\"Task 2\"<\/span>)\n    <span class=\"hljs-keyword\">go<\/span> task(<span class=\"hljs-string\">\"Task 3\"<\/span>)\n\n    fmt.Println(<span class=\"hljs-string\">\"Done\"<\/span>)\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">Done\nIt took <span class=\"hljs-number\">0<\/span> ms<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It seems that the <code>task()<\/code> function was not executed at all. The reason is that the <code>main()<\/code> function ran so fast, that the <code>task()<\/code> function did not get a chance to execute:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"490\" height=\"515\" src=\"https:\/\/gotutorial.org\/wp-content\/uploads\/2024\/09\/goroutines-without-waitgroup-1.png\" alt=\"\" class=\"wp-image-344\" srcset=\"https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/goroutines-without-waitgroup-1.png 490w, https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/goroutines-without-waitgroup-1-285x300.png 285w\" sizes=\"auto, (max-width: 490px) 100vw, 490px\" \/><\/figure>\n\n\n\n<p>To allow the <code>task()<\/code> function to run, the <code>main()<\/code> function must wait for the goroutines to run to complete. <\/p>\n\n\n\n<p>Go provides synchronization primitives to do it:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Using <code>WaitGroup<\/code> objects from the sync module.<\/li>\n\n\n\n<li>Using <em>Channels<\/em>.<\/li>\n<\/ul>\n\n\n\n<p>We&#8217;ll focus on the <code>WaitGroup<\/code> in this tutorial.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Go WaitGroup<\/h2>\n\n\n\n<p>In Go, <code>WaitGroup<\/code> is used to wait for a group of goroutines to complete execution. <\/p>\n\n\n\n<p>A <code>WaitGroup<\/code> works like a counter: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First, set the initial counter value which represents the number of goroutines to wait for.<\/li>\n\n\n\n<li>Second, decrease the counter value each time a goroutine is completed.<\/li>\n\n\n\n<li>Third, wait until the counter becomes zero.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Using a WaitGroup<\/h3>\n\n\n\n<p>Here are the steps for using <code>WaitGroup<\/code>:<\/p>\n\n\n\n<p>First, declare a variable with the <code>sync.WaitGroup<\/code> type:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">var<\/span> wg sync.WaitGroup<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, set the counter for the <code>WaitGroup<\/code> to <code>n<\/code>, which represents the number of goroutines to wait for:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">wg.Add(n)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, call the <code>Done()<\/code> function in the goroutine to decrement the counter once the goroutine completes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">defer<\/span> wg.Done()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Finally, call the <code>wg.Wait<\/code>() function to wait until all goroutine completes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">wg.Wait()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Go WaitGroup example<\/h3>\n\n\n\n<p>The following example shows how to use a <code>WaitGroup<\/code> to wait for all the goroutines to complete:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">package<\/span> main\n\n<span class=\"hljs-keyword\">import<\/span> (\n    <span class=\"hljs-string\">\"fmt\"<\/span>\n    <span class=\"hljs-string\">\"sync\"<\/span>\n    <span class=\"hljs-string\">\"time\"<\/span>\n)\n\n<span class=\"hljs-keyword\">var<\/span> wg sync.WaitGroup\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n    <span class=\"hljs-comment\">\/\/ measure the execution time<\/span>\n    start := time.Now()\n    <span class=\"hljs-keyword\">defer<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n        elapsed := time.Since(start)\n        fmt.Printf(<span class=\"hljs-string\">\"It took %d ms\\n\"<\/span>, elapsed.Milliseconds())\n    }()\n\n    wg.Add(<span class=\"hljs-number\">3<\/span>)\n\n    <span class=\"hljs-keyword\">go<\/span> task(<span class=\"hljs-string\">\"Task 1\"<\/span>)\n    <span class=\"hljs-keyword\">go<\/span> task(<span class=\"hljs-string\">\"Task 2\"<\/span>)\n    <span class=\"hljs-keyword\">go<\/span> task(<span class=\"hljs-string\">\"Task 3\"<\/span>)\n\n    wg.Wait()\n\n    fmt.Println(<span class=\"hljs-string\">\"Done\"<\/span>)\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">task<\/span><span class=\"hljs-params\">(name <span class=\"hljs-keyword\">string<\/span>)<\/span><\/span> {\n    <span class=\"hljs-keyword\">defer<\/span> wg.Done()\n\n    fmt.Println(name, <span class=\"hljs-string\">\"started...\"<\/span>)\n    time.Sleep(<span class=\"hljs-number\">1<\/span> * time.Second)\n    fmt.Println(name, <span class=\"hljs-string\">\"finished\"<\/span>)\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">Task <span class=\"hljs-number\">3<\/span> started...\nTask <span class=\"hljs-number\">1<\/span> started...\nTask <span class=\"hljs-number\">2<\/span> started...\nTask <span class=\"hljs-number\">2<\/span> finished\nTask <span class=\"hljs-number\">1<\/span> finished\nTask <span class=\"hljs-number\">3<\/span> finished\nDone\nIt took <span class=\"hljs-number\">1000<\/span> ms<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The output shows two important things:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First, goroutines did not execute in any order.<\/li>\n\n\n\n<li>Second, the program took roughly 1 second to complete. It&#8217;s three times faster than the synchronous program on our computer.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"681\" height=\"506\" src=\"https:\/\/gotutorial.org\/wp-content\/uploads\/2024\/09\/go-WaitGroup.png\" alt=\"go WaitGroup\" class=\"wp-image-345\" srcset=\"https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/go-WaitGroup.png 681w, https:\/\/www.gotutorial.org\/wp-content\/uploads\/2024\/09\/go-WaitGroup-300x223.png 300w\" sizes=\"auto, (max-width: 681px) 100vw, 681px\" \/><\/figure>\n\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, declare a variable with the type <code>WaitGroup<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">var<\/span> wg sync.WaitGroup<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, set the <code>WaitGroup<\/code>&#8216;s counter to three to wait for three goroutines to complete before creating goroutines:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">wg.Add(<span class=\"hljs-number\">3<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, launch three goroutines:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">go<\/span> task(<span class=\"hljs-string\">\"Task 1\"<\/span>)\n<span class=\"hljs-keyword\">go<\/span> task(<span class=\"hljs-string\">\"Task 2\"<\/span>)\n<span class=\"hljs-keyword\">go<\/span> task(<span class=\"hljs-string\">\"Task 3\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Fifth, call the <code>Wait()<\/code> function to wait for all the goroutines to complete:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">wg.Wait()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Sixth, when executing the <code>task()<\/code> function, decrement the counter of the <code>WaitGroup<\/code> by one when it completes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">defer<\/span> wg.Done()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Goroutine practical example<\/h2>\n\n\n\n<p>The following example shows how to use goroutines to check the status of multiple URLs:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">package<\/span> main\n\n<span class=\"hljs-keyword\">import<\/span> (\n    <span class=\"hljs-string\">\"fmt\"<\/span>\n    <span class=\"hljs-string\">\"net\/http\"<\/span>\n    <span class=\"hljs-string\">\"sync\"<\/span>\n)\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">check<\/span><span class=\"hljs-params\">(url <span class=\"hljs-keyword\">string<\/span>, wg *sync.WaitGroup)<\/span><\/span> {\n    <span class=\"hljs-keyword\">defer<\/span> wg.Done()\n    _, err := http.Get(url)\n    <span class=\"hljs-keyword\">if<\/span> err != <span class=\"hljs-literal\">nil<\/span> {\n        fmt.Printf(<span class=\"hljs-string\">\"The %s is down\\n\"<\/span>, url)\n    } <span class=\"hljs-keyword\">else<\/span> {\n        fmt.Printf(<span class=\"hljs-string\">\"The %s is up\\n\"<\/span>, url)\n    }\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n    <span class=\"hljs-keyword\">var<\/span> wg sync.WaitGroup\n    urls := &#91;]<span class=\"hljs-keyword\">string<\/span>{\n        <span class=\"hljs-string\">\"https:\/\/www.google.com\"<\/span>,\n        <span class=\"hljs-string\">\"https:\/\/www.bing.com\"<\/span>,\n        <span class=\"hljs-string\">\"https:\/\/www.duckduckgo.com\/\"<\/span>,\n    }\n\n    wg.Add(<span class=\"hljs-built_in\">len<\/span>(urls))\n\n    <span class=\"hljs-keyword\">for<\/span> _, url := <span class=\"hljs-keyword\">range<\/span> urls {\n        <span class=\"hljs-keyword\">go<\/span> check(url, &amp;wg)\n    }\n    wg.Wait()\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>Step 1. Define the <code>check()<\/code> function that checks the status of a URL and displays whether the URL is up or down:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">check<\/span><span class=\"hljs-params\">(url <span class=\"hljs-keyword\">string<\/span>, wg *sync.WaitGroup)<\/span><\/span> {\n    <span class=\"hljs-keyword\">defer<\/span> wg.Done()\n    _, err := http.Get(url)\n    <span class=\"hljs-keyword\">if<\/span> err != <span class=\"hljs-literal\">nil<\/span> {\n        fmt.Printf(<span class=\"hljs-string\">\"The %s is down\\n\"<\/span>, url)\n    } <span class=\"hljs-keyword\">else<\/span> {\n        fmt.Printf(<span class=\"hljs-string\">\"The %s is up\\n\"<\/span>, url)\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Step 2. Define a variable for the <code>WaitGroup<\/code> type<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">var<\/span> wg sync.WaitGroup<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Step 3. Declare and initialize a slice of strings, which hold a list of URLs to check:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">urls := &#91;]<span class=\"hljs-keyword\">string<\/span>{\n    <span class=\"hljs-string\">\"https:\/\/www.google.com\"<\/span>,\n    <span class=\"hljs-string\">\"https:\/\/www.bing.com\"<\/span>,\n    <span class=\"hljs-string\">\"https:\/\/www.duckduckgo.com\/\"<\/span>,\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Step 4. Set the counter of the <code>WaitGroup<\/code> to the size of the <code>urls<\/code> slice:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">wg.Add(<span class=\"hljs-built_in\">len<\/span>(urls))<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Step 5. iterate over the <code>URLs<\/code> and create each goroutine to check <\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-keyword\">for<\/span> _, url := <span class=\"hljs-keyword\">range<\/span> urls {\n    <span class=\"hljs-keyword\">go<\/span> check(url, &amp;wg)\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Step 6. Wait for all goroutines to complete:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">wg.Wait()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here&#8217;s the output of the program:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">The https:<span class=\"hljs-comment\">\/\/www.google.com is up<\/span>\nThe https:<span class=\"hljs-comment\">\/\/www.bing.com is up<\/span>\nThe https:<span class=\"hljs-comment\">\/\/www.duckduckgo.com\/ is up<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Please note that the sequence of the <code>URLs<\/code> may vary. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Goroutines are lightweight threads managed by Go runtime.<\/li>\n\n\n\n<li>Use <code>go<\/code> keyword followed by a function call to run the function asynchronously.<\/li>\n\n\n\n<li>Use <code>WaitGroup<\/code> to wait for a collection of goroutines to finish executing.<\/li>\n<\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<div class=\"wth-question\">Was this tutorial helpful?<\/div>\n\t<div class=\"wth-thumbs\">\n\t\t<button\n\t\t\tdata-post=\"294\"\n\t\t\tdata-post-url=\"https:\/\/www.gotutorial.org\/go-tutorial\/goroutines\/\"\n\t\t\tdata-post-title=\"Goroutines\"\n\t\t\tdata-response=\"1\"\n\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t>\n\t\t\t<svg\n\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstroke-width=\"2\"\n\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t>\n\t\t\t\t<path\n\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t><\/path>\n\t\t\t<\/svg>\n\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t<\/button>\n\n\t\t<button\n\t\t\tdata-response=\"0\"\n\t\t\tdata-post=\"294\"\n\t\t\tdata-post-url=\"https:\/\/www.gotutorial.org\/go-tutorial\/goroutines\/\"\n\t\t\tdata-post-title=\"Goroutines\"\n\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t>\n\t\t\t<svg\n\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstroke-width=\"2\"\n\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t>\n\t\t\t\t<path\n\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t><\/path>\n\t\t\t<\/svg>\n\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t<\/button>\n\t<\/div>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\t\t\t<input type=\"button\" name=\"wth-submit\" class=\"wth-btn wth-btn-submit\" id=\"wth-submit\" \/>\n\t\t\t<input type=\"button\" class=\"wth-btn wth-btn-cancel\" value=\"Cancel\" \/>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you will learn how to use goroutines to develop concurrent applications that run functions asynchronously using go keyword.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":10,"menu_order":26,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-294","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.gotutorial.org\/wp-json\/wp\/v2\/pages\/294","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gotutorial.org\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.gotutorial.org\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.gotutorial.org\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gotutorial.org\/wp-json\/wp\/v2\/comments?post=294"}],"version-history":[{"count":20,"href":"https:\/\/www.gotutorial.org\/wp-json\/wp\/v2\/pages\/294\/revisions"}],"predecessor-version":[{"id":408,"href":"https:\/\/www.gotutorial.org\/wp-json\/wp\/v2\/pages\/294\/revisions\/408"}],"up":[{"embeddable":true,"href":"https:\/\/www.gotutorial.org\/wp-json\/wp\/v2\/pages\/10"}],"wp:attachment":[{"href":"https:\/\/www.gotutorial.org\/wp-json\/wp\/v2\/media?parent=294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}