并发编程是现代计算机编程中的一个重要概念,它允许程序员编写同时执行多个任务的程序。在Golang中,并发编程被简化为一种非常直观的方式,通过goroutines和channels来实现。以下是通过5个实战示例,帮助你入门Golang并发编程。
示例1:打印数字序列
这个简单的示例展示了如何使用goroutines来并行打印数字序列。
package main
import (
"fmt"
"sync"
)
func printNumbers(wg *sync.WaitGroup, start, end int) {
for i := start; i <= end; i++ {
fmt.Println(i)
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
go printNumbers(&wg, 1, 10)
go printNumbers(&wg, 11, 20)
wg.Wait()
}
在这个例子中,我们创建了两个goroutines,每个goroutine负责打印一个数字序列。sync.WaitGroup用于等待所有goroutines完成。
示例2:计算斐波那契数列
斐波那契数列是一个经典的并发编程示例。以下是一个使用goroutines和channels来计算斐波那契数列的例子。
package main
import (
"fmt"
)
func fibonacci(n int, ch chan int) {
if n <= 1 {
ch <- n
return
}
go fibonacci(n-1, ch)
go fibonacci(n-2, ch)
for i := range ch {
if i%2 == 0 {
ch <- i
}
}
}
func main() {
ch := make(chan int)
go fibonacci(10, ch)
for i := range ch {
fmt.Println(i)
}
}
在这个例子中,我们使用递归和channels来计算斐波那契数列。当计算到偶数时,结果会被发送到channel中。
示例3:处理HTTP请求
Golang的net/http包提供了强大的并发处理能力。以下是一个简单的HTTP服务器示例,它使用goroutines来处理并发请求。
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!\n", r.URL.Path)
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
在这个例子中,每个HTTP请求都会在一个新的goroutine中处理,从而实现并发。
示例4:生成随机数
生成随机数是一个很好的并发编程练习。以下是一个使用goroutines和channels生成随机数的例子。
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func generateRandomNumbers(wg *sync.WaitGroup, num int, ch chan int) {
defer wg.Done()
for i := 0; i < num; i++ {
ch <- rand.Intn(100)
}
}
func main() {
var wg sync.WaitGroup
ch := make(chan int, 10)
wg.Add(2)
go generateRandomNumbers(&wg, 5, ch)
go generateRandomNumbers(&wg, 5, ch)
go func() {
wg.Wait()
close(ch)
}()
for i := range ch {
fmt.Println(i)
}
}
在这个例子中,我们创建了两个goroutines来生成随机数,并将结果发送到channel中。
示例5:并行下载文件
以下是一个使用goroutines和channels并行下载文件的例子。
package main
import (
"fmt"
"io"
"net/http"
"os"
"sync"
)
func downloadFile(url string, wg *sync.WaitGroup, done chan<- bool) {
defer wg.Done()
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error downloading file:", err)
return
}
defer resp.Body.Close()
out, err := os.Create(url)
if err != nil {
fmt.Println("Error creating file:", err)
return
}
defer out.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
fmt.Println("Error copying file:", err)
return
}
done <- true
}
func main() {
urls := []string{
"https://example.com/file1.zip",
"https://example.com/file2.zip",
"https://example.com/file3.zip",
}
var wg sync.WaitGroup
done := make(chan bool, len(urls))
for _, url := range urls {
wg.Add(1)
go downloadFile(url, &wg, done)
}
go func() {
wg.Wait()
close(done)
}()
for i := range done {
fmt.Println("File downloaded:", i)
}
}
在这个例子中,我们创建了多个goroutines来并发下载文件,并使用channels来跟踪下载进度。
通过以上5个实战示例,你将能够更好地理解Golang并发编程的基本概念和技巧。记住,实践是学习编程的关键,尝试自己实现这些示例,并在此基础上进行扩展和改进。祝你编程愉快!
