一、常见题目
1.1 三个协程交替打印ABC
建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。
package main
import("fmt""sync"
)
var wg sync.WaitGroup
var ch1, ch2, ch3 = make(chan int), make(chan int), make(chan int)
func print_A(){defer wg.Done()for i := 0; i < 10; i++ {<- ch1fmt.Print("A")ch2 <- 1}<- ch1
}func print_B(){defer wg.Done()for i := 0; i < 10; i++{// a.Done()// fmt.Print("B")// b.Add(1)<- ch2fmt.Print("B")ch3 <- 1}
}func print_C(){// print_C运行结束wg再-1defer wg.Done()for i := 0; i < 10; i++{<- ch3fmt.Print("C")ch1 <- 1}
}
// 建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,
// 但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。func main(){// wg确保main函数在所有协程运行完毕再退出wg.Add(3)go print_A()go print_B()go print_C()// 确保所有 goroutine 都已经启动并准备好接收信号,然后再发送第一个信号。这样可以避免在开始时出现竞争条件或死锁。ch1 <- 1wg.Wait()fmt.Println(" Done")
}
1.2 并发访问多个URL,存储状态信息
package mainimport ("fmt""net/http""sync"
)// fetchURL 发送 HTTP GET 请求并返回响应状态码,如果请求出错则返回错误信息。
func fetchURL(url string) (string, error) {resp, err := http.Get(url)if err != nil {return "", err}defer resp.Body.Close()// fmt.Printf("Fetched %s with status: %s\n", url, resp.Status) // 调试输出return resp.Status, nil
}func main() {urls := []string{"https://www.zijie.com","https://www.baidu.com","https://www.alibaba.com",// 添加更多的 URL...}results := make(chan string)var wg sync.WaitGroup// 启动 goroutine 发送 HTTP 请求for _, url := range urls {// _:0,1,2wg.Add(1) // 每个 goroutine 开始前增加 WaitGroup 的计数器go func(url string) {defer wg.Done()data, err := fetchURL(url)if err != nil {fmt.Println("Error fetching", url, ":", err)return}// data写给管道results <- data// url作为参数}(url)}// 启动一个 goroutine 等待所有任务完成后关闭通道go func() {wg.Wait() // 等待所有 goroutine 完成close(results) // 当所有请求处理完毕后关闭通道,告知 range 循环停止}()// 从通道中读取并处理每个 URL 请求的响应状态码for result := range results {// 这里可以将获取到的数据进行处理,例如打印或保存到文件中fmt.Println(result)}
}
1.3 生成随机数并且计算各个位数之和再打印
// 使用 goroutine 和 channel 实现一个计算int64随机数各位数和的程序,例如生成随机数61345,计算其每个位数上的数字之和为19。// 1. 开启一个 goroutine 循环生成int64类型的随机数,发送到`jobChan`
// 2. 开启24个 goroutine 从`jobChan`中取出随机数计算各位数的和,将结果发送到`resultChan`
// 3. 主 goroutine 从`resultChan`取出结果并打印到终端输出package mainimport ("fmt""math/rand""sync"
)// ch1, ch2:= make(chan int),make(chan int)func cal_num(n int64) int{sum := 0for n != 0{sum += int(n%10)n /= 10}// fmt.Println(n, "数字之和", sum)return sum
}func main(){jobChan,resultChan:= make(chan int64),make(chan int)var wg sync.WaitGroup// 开启一个 goroutine 循环生成int64类型的随机数,发送到`jobChan`go func () {for{randomNumber := rand.Int63()jobChan <-randomNumber}}()// 开启24个 goroutine 从`jobChan`中取出随机数计算各位数的和,将结果发送到`resultChan`for i :=0;i<24;i++{wg.Add(1)go func () {defer wg.Done()for{select{case num:= <- jobChan:sum := cal_num(num)// fmt.Println(num, "数字之和", sum)resultChan <- sum}}}()}go func(){for c:=range resultChan{fmt.Println(c)}}()wg.Wait() // 等待所有 goroutine 完成
}