好享购物官方网站购物,wordpress超链接下划线,川制作官方网站,网络营销是什么研究文章目录 用 goroutine 和通道实现并发用 sync 实现并发互斥锁sync.Once 结构体同步等待组 zync.WaitGroup竞态检测器 应用自增整数生成器并发消息发送器多路复合计算器用 select 关键字创建多通道监听器多路复合计算器超时处理 用无缓冲通道阻塞主线程用筛法求素数创建随机数生… 文章目录 用 goroutine 和通道实现并发用 sync 实现并发互斥锁sync.Once 结构体同步等待组 zync.WaitGroup竞态检测器 应用自增整数生成器并发消息发送器多路复合计算器用 select 关键字创建多通道监听器多路复合计算器超时处理 用无缓冲通道阻塞主线程用筛法求素数创建随机数生成器创建一个定时器Go Web爬虫 用 goroutine 和通道实现并发
package mainimport (fmt
)func main() {ch : make(chan string) // 构建一个通道go func() { // 开启一个并发匿名函数fmt.Println(开始协程) // 通过通道通知main的协程ch - signalfmt.Println(退出协程)}()fmt.Println(等待协程)-ch // 等待匿名协程fmt.Println(完成)
}
package mainimport fmtfunc main() {// 这里我们定义了一个可以存储整数类型的带缓冲通道缓冲区大小为3ch : make(chan int, 3)// 因为 ch 是带缓冲的通道我们可以同时发送两个数据// 而不用立刻需要去同步读取数据ch - 6ch - 7ch - 8// 获取这三个数据fmt.Println(-ch)fmt.Println(-ch)fmt.Println(-ch)
}
package mainimport (fmt
)func fibonacci(n int, ch chan int) {a, b : 0, 1for i : 0; i n; i {ch - aa, b b, ab}close(ch)
}func main() {ch : make(chan int, 6)go fibonacci(cap(ch), ch)for j : range ch {fmt.Println(j)}
}
用 sync 实现并发
互斥锁
package mainimport (fmtsynctime
)func main() {var mutex sync.Mutexwait : sync.WaitGroup{}fmt.Println(Locked)mutex.Lock()for i : 1; i 5; i {wait.Add(1)go func(i int) {fmt.Println(Not lock:, i)mutex.Lock()fmt.Println(Lock:, i)time.Sleep(time.Second)fmt.Println(Unlock:, i)mutex.Unlock()defer wait.Done()}(i)}time.Sleep(time.Second)fmt.Println(Unlocked)mutex.Unlock()wait.Wait()
}sync.Once 结构体
package mainimport (fmtsync
)func main() {var once sync.OnceonceBody : func() {fmt.Println(test only once这里只打印一次)//打印}done : make(chan bool)for i : 0; i 6; i {go func() {once.Do(onceBody)//确保只背执行一次done - true}()}for i : 0; i 6; i {-done}
}
同步等待组 zync.WaitGroup
package mainimport (fmtsynctime
)func main() {var wg sync.WaitGroupwg.Add(1)go func() {defer wg.Done()fmt.Println(1 goroutine sleep ...)time.Sleep(2)fmt.Println(1 goroutine exit ...)}()wg.Add(1)go func() {defer wg.Done()fmt.Println(2 goroutine sleep ...)time.Sleep(4)fmt.Println(2 goroutine exit ...)}()fmt.Println(Waiting for all goroutine )wg.Wait()fmt.Println(All goroutines finished!)
}package mainimport (fmtsynctime
)func main() {testFunc : func(wg *sync.WaitGroup, id int) {defer wg.Done()fmt.Printf(%v goroutine start ...\n, id)time.Sleep(2)fmt.Printf(%v goroutine exit ...\n, id)}var wg sync.WaitGroupconst N 3wg.Add(N)for i : 0; i N; i {go testFunc(wg, i)}fmt.Println(Waiting for all goroutine)wg.Wait()fmt.Println(All goroutines finished!)
}
竞态检测器
go run/build/test -race main.go模拟非法竞态访问数据
package mainimport fmtfunc main() {c : make(chan bool)m : make(map[string]string)go func() {m[a] one // 第一个冲突访问.c - true}()m[b] two // 第一个冲突访问-cfor k, v : range m {fmt.Println(k, v)}
}
应用
自增整数生成器
package mainimport fmt// 生成自增的整数
func IntegerGenerator() chan int {var ch chan int make(chan int)// 开启 goroutinego func() {for i : 0; ; i {ch - i // 直到通道索要数据才把i添加进信道}}()return ch
}func main() {generator : IntegerGenerator()for i : 0; i 100; i { //生成100个自增的整数fmt.Println(-generator)}
}
并发消息发送器
package mainimport fmtfunc SendNotification(user string) chan string {//......此处省略查询数据库获取新消息。//声明一个通道来保存消息notifications : make(chan string, 500)// 开启一个通道go func() {//将消息放入通道notifications - fmt.Sprintf(Hi %s, welcome to our site!, user)}()return notifications
}func main() {barry : SendNotification(barry) // 获取barry的消息shirdon : SendNotification(shirdon) // 获取shirdon的消息// 获取消息的返回fmt.Println(-barry)fmt.Println(-shirdon)
}
多路复合计算器
package mainimport (fmtmath/randtime
)// 这里可以是比较耗时的事情比如计算
func doCompute(x int) int {time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond) //模拟计算return 1 x // 假如1 x是一个很费时的计算
}// 每个分支开出一个goroutine做计算并把计算结果发送到各自通道
func branch(x int) chan int {ch : make(chan int)go func() {ch - doCompute(x)}()return ch
}func Recombination(chs ...chan int) chan int {ch : make(chan int)for _, c : range chs {// 注意此处明确传值go func(c chan int) { ch - -c }(c) // 复合}return ch
}func main() {//返回复合结果result : Recombination(branch(10), branch(20), branch(30))for i : 0; i 3; i {fmt.Println(-result)}
}
用 select 关键字创建多通道监听器
package mainimport (fmt
)func foo(i int) chan int {ch : make(chan int)go func() { ch - i }()return ch
}func main() {ch1, ch2, ch3 : foo(3), foo(6), foo(9)ch : make(chan int)// 开一个goroutine监视各个通道数据输出并收集数据到通道chgo func() {for {// 监视ch1, ch2, ch3的流出并全部流入通道chselect {case v1 : -ch1:ch - v1case v2 : -ch2:ch - v2case v3 : -ch3:ch - v3}}}()// 阻塞主线取出通道ch的数据for i : 0; i 3; i {fmt.Println(-ch)}}
多路复合计算器
package mainimport (fmtmath/randtime
)//这里可以是比较耗时的事情比如计算
func doCompute(x int) int {time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond) //模拟计算return 1 x // 假如1 x是一个很费时的计算
}// 每个分支开出一个goroutine做计算并把计算结果发送到各自通道
func branch(x int) chan int {ch : make(chan int)go func() {ch - doCompute(x)}()return ch
}func Recombination(branches ... chan int) chan int {ch : make(chan int)//select会尝试着依次取出各个通道的数据go func() {for i : 0; i len(branches); i {select {case v1 : -branches[i]:ch - v1}}}()return ch
}func main() {//返回复合结果result : Recombination(branch(10), branch(20), branch(30))for i : 0; i 3; i {fmt.Println(-result)}
}
超时处理 //timeout 是一个计时通道, 如果达到时间了就会发一个信号出来timeout : time.After(1 * time.Second)for isTimeout : false; !isTimeout; {select { // 监视通道ch1, ch2, ch3, timeout通道的数据流出case v1 : -ch1:fmt.Printf(received %d from ch1, v1)case v2 : -ch2:fmt.Printf(received %d from ch2, v2)case v3 : -ch3:fmt.Printf(received %d from ch3, v3)case -timeout:isTimeout true // 超时}}用无缓冲通道阻塞主线程
package mainimport (fmt
)func main() {ch, quit : make(chan int), make(chan int)go func() {ch - 8 // 添加数据quit - 1 // 发送完成信号}()for isQuit : false; !isQuit; {// 监视通道ch的数据流出select {case v : -ch:fmt.Printf(received %d from ch, v)case -quit:isQuit true // quit通道有输出关闭for循环}}
}用筛法求素数
package mainimport fmt//生成自增的整数
func IntegerGenerator() chan int {var ch chan int make(chan int)go func() { // 开出一个goroutinefor i : 2; ; i {ch - i // 直到通道索要数据才把i添加进通道}}()return ch
}func Filter(in chan int, number int) chan int {// 输入一个整数队列筛出是number倍数的, 不是number的倍数的放入输出队列// in: 输入队列out : make(chan int)go func() {for {i : -in // 从输入中取一个if i%number ! 0 {out - i // 放入输出通道}}}()return out
}func main() {const max 100 // 找出100以内的所有素数numbers : IntegerGenerator() // 初始化一个整数生成器number : -numbers // 从生成器中抓一个整数(2), 作为初始化整数for number max { // number作为筛子当筛子超过max的时候结束筛选fmt.Println(number) // 打印素数, 筛子即一个素数numbers Filter(numbers, number) //筛掉number的倍数number -numbers // 更新筛子}
}
创建随机数生成器
package mainimport fmtfunc randGenerator() chan int {ch : make(chan int)go func() {for {//select会尝试执行各个case, 如果都可以执行那么随机选一个执行select {case ch - 0:case ch - 1:}}}()return ch
}func main() {//初始化一个随机生成器generator : randGenerator()//测试打印10个随机数for i : 0; i 10; i {fmt.Println(-generator)}
}
创建一个定时器
package mainimport (fmttime
)func Timer(duration time.Duration) chan bool {ch : make(chan bool)go func() {time.Sleep(duration)// 到时间啦ch - true}()return ch}func main() {// 定时5秒timeout : Timer(5 * time.Second)for {select {case -timeout:// 到时fmt.Println(already 5s!)//结束程序return}}
}
Go Web爬虫
package mainimport (fmtionet/httposstrconv
)func Get(url string) (result string, err error) {resp, err : http.Get(url) // 修改此行if err ! nil {return , err}defer resp.Body.Close()// 读取网页的body内容buf : make([]byte, 4*1024)for {n, err : resp.Body.Read(buf)if err ! nil {if err io.EOF {fmt.Println(文件读取完毕)break} else {fmt.Println(resp.Body.Read err , err)break}}result string(buf[:n])}return result, nil // 修改此行
}// 将所有的网页内容爬取下来
func SpiderPage(i int, page chan- int) {url : https://github.com/search?qgotypeRepositoriesp1 strconv.Itoa((i-1)*50)fmt.Printf(正在爬取第%d个网页\n, i)//爬,将所有的网页内容爬取下来result, err : Get(url)if err ! nil {fmt.Println(http.Get err , err)return}//把内容写入到文件filename : page strconv.Itoa(i) .htmlf, err : os.Create(filename)if err ! nil {fmt.Println(os.Create err , err)return}//写内容f.WriteString(result)//关闭文件f.Close()//每爬完一个就给个值page - i
}func Run(start, end int) {fmt.Printf(正在爬取第%d页到%d页\n, start, end)//因为很有可能爬虫还没有结束下面的循环就已经结束了所以这里就需要且到通道page : make(chan int)for i : start; i end; i {//将page阻塞go SpiderPage(i, page)}for i : start; i end; i {fmt.Printf(第%d个页面爬取完成\n, -page) //这里直接将面码传给点位符值直接从管道里取出}
}func main() {var start, end intfmt.Printf(请输入起始页数字1 )fmt.Scan(start)fmt.Printf(请输入结束页数字 )fmt.Scan(end)Run(start, end)
}