go并发请求url

复制代码
sync.WaitGroup写法
Go 复制代码
package main

import (
	"database/sql"
	"fmt"
	"net/http"
	"sync"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	//开始计时
	start := time.Now()

	//链接数据库,用户名:密码@tcp(地址:端口)/数据库名
	dsn := "gin:gin@tcp(42.1.25.18:3306)/gin"
	// 连接到MySQL数据库
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		fmt.Println("数据库连接错误: ", err)
		return
	}
	defer db.Close()

	urls := []string{
		"https://www.baidu.com",
		"https://www.taobao.com",
		"https://www.tmall.com",
		"https://www.jd.com",
		"https://www.sina.com.cn",
		"https://www.sohu.com",
		"https://www.qq.com",
		"https://www.163.com",
		"https://www.zhihu.com",
		"https://www.weibo.com",
		"https://www.bilibili.com",
		"https://www.youku.com",
		"https://www.iqiyi.com",
		"https://www.alipay.com",
		"https://www.dingtalk.com",
		"https://www.wechat.com",
		"https://www.360.cn",
		"https://www.58.com",
		"https://www.liepin.com",
		"https://www.zhaopin.com",
		"https://www.douban.com",
		"https://www.ifeng.com",
		"https://www.ctrip.com",
		"https://www.qunar.com",
		"https://www.meituan.com",
		"https://www.dianping.com",
		"https://www.ele.me",
		"https://www.vip.com",
		"https://www.suning.com",
		"https://www.mi.com",
		"https://www.huawei.com",
		"https://www.vivo.com.cn",
		"https://www.oppo.com",
		"https://www.le.com",
		"https://www.ganji.com",
		"https://www.kuaidi100.com",
		"https://www.17173.com",
		"https://www.4399.com",
		"https://www.tgbus.com",
		"https://www.10010.com",
		"https://www.10086.cn",
		"https://www.189.cn",
		"https://www.21cn.com",
		"https://www.chinadaily.com.cn",
		"https://www.xinhuanet.com",
		"https://www.people.com.cn",
		"https://www.thepaper.cn",
		"https://www.guokr.com",
		"https://www.ftchinese.com",
		"https://www.cbnweek.com",
		"https://www.163.com",
		"https://www.sina.com.cn",
		"https://www.sohu.com",
		"https://www.qq.com",
		"https://e.baidu.com",
		"https://hezuo.baidu.com",
		"https://yiyan.baidu.com",
	}

	//设置3s超时,避免请求时间过长
	client := http.Client{
		Timeout: 3 * time.Second,
	}

	//定义chan结构体,url,status
	type Web struct {
		url    string
		status string
	}

	//并发请求,定义一个WaitGroup,用于等待所有请求完成
	var wg sync.WaitGroup

	for _, url := range urls {
		//增加一个等待
		wg.Add(1)
		//启动一个goroutine
		go func(url string) {
			//协程结束时调用Done通知main函数工作已经完成
			defer wg.Done()
			//请求
			resp, err := client.Get(url)
			if err != nil {
				fmt.Println("请求失败", err)
				_, err := db.Exec("INSERT INTO web (url, status) VALUES (?, ?)", url, "请求失败")
				if err != nil {
					return
				}
			} else {
				// 写入数据库
				_, err1 := db.Exec("INSERT INTO web (url, status) VALUES (?, ?)", url, resp.StatusCode)
				if err1 != nil {
					fmt.Println("写入数据库错误:", err1)
					return
				}
			}
		}(url)
	}

	//等待所有请求完成
	wg.Wait()

	//输出耗时
	elapsed := time.Since(start)
	fmt.Println("耗时:", elapsed)
}

sync.WaitGroup+channel

Go 复制代码
package main

import (
	"database/sql"
	"fmt"
	"net/http"
	"strconv"
	"sync"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	//开始计时
	start := time.Now()

	//链接数据库,用户名:密码@tcp(地址:端口)/数据库名
	dsn := "gin:gin@tcp(4.19.21.17:3306)/gin"
	// 连接到MySQL数据库
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		fmt.Println("数据库连接错误: ", err)
		return
	}
	//关闭数据库
	defer db.Close()

	urls := []string{
		"https://www.baidu.com",
		"https://www.taobao.com",
		"https://www.tmall.com",
		"https://www.jd.com",
		"https://www.sina.com.cn",
		"https://www.sohu.com",
		"https://www.qq.com",
		"https://www.163.com",
		"https://www.zhihu.com",
		"https://www.weibo.com",
		"https://www.bilibili.com",
		"https://www.youku.com",
		"https://www.iqiyi.com",
		"https://www.alipay.com",
		"https://www.dingtalk.com",
		"https://www.wechat.com",
		"https://www.360.cn",
		"https://www.58.com",
		"https://www.liepin.com",
		"https://www.zhaopin.com",
		"https://www.douban.com",
		"https://www.ifeng.com",
		"https://www.ctrip.com",
		"https://www.qunar.com",
		"https://www.meituan.com",
		"https://www.dianping.com",
		"https://www.ele.me",
		"https://www.vip.com",
		"https://www.suning.com",
		"https://www.mi.com",
		"https://www.huawei.com",
		"https://www.vivo.com.cn",
		"https://www.oppo.com",
		"https://www.le.com",
		"https://www.ganji.com",
		"https://www.kuaidi100.com",
		"https://www.17173.com",
		"https://www.4399.com",
		"https://www.tgbus.com",
		"https://www.10010.com",
		"https://www.10086.cn",
		"https://www.189.cn",
		"https://www.21cn.com",
		"https://www.chinadaily.com.cn",
		"https://www.xinhuanet.com",
		"https://www.people.com.cn",
		"https://www.thepaper.cn",
		"https://www.guokr.com",
		"https://www.ftchinese.com",
		"https://www.cbnweek.com",
		"https://www.163.com",
		"https://www.sina.com.cn",
		"https://www.sohu.com",
		"https://www.qq.com",
		"https://e.baidu.com",
		"https://hezuo.baidu.com",
		"https://yiyan.baidu.com",
	}

	//设置3s超时,避免请求时间过长
	client := http.Client{
		Timeout: 3 * time.Second,
	}

	//定义chan结构体,url,status
	type Web struct {
		url    string
		status string
	}

	//并发请求
	var wg sync.WaitGroup
	//创建一个并发请求的channel,缓冲区大小为urls的长度
	results := make(chan *Web, len(urls))

	//遍历urls,k为索引,url为值
	for k, url := range urls {
		//增加一个等待
		wg.Add(1)
		fmt.Println("开始请求:", k, url)
		//启动一个goroutine,传入k和url
		go func(k int, url string) {
			//协程结束时调用Done通知main函数工作已经完成
			defer wg.Done()
			//请求
			resp, err := client.Get(url)
			if err != nil {
				fmt.Println("请求失败", err)
				//设置状态为请求失败
				results <- &Web{url: url, status: "请求失败"}
				return
			}
			//关闭请求
			defer resp.Body.Close()
			fmt.Println("请求完成:", k, url)
			//写入channel
			results <- &Web{url: url, status: strconv.Itoa(resp.StatusCode)}
		}(k, url)
	}

	//统计有多少个请求完成了
	fmt.Println("等待所有请求完成")
	//等待所有请求完成
	wg.Wait()
	//关闭channel
	close(results)
	//统计results的长度
	//fmt.Println("results长度:", len(results))

	fmt.Println("开始写入数据库")
	//遍历channel
	for resp := range results {
		// 写入数据库
		_, err := db.Exec("INSERT INTO web (url, status) VALUES (?, ?)", resp.url, resp.status)
		if err != nil {
			fmt.Println("写入数据库错误:", err)
		}
	}
	fmt.Println("写入数据库完成")

	//输出耗时
	elapsed := time.Since(start)
	fmt.Println("耗时:", elapsed)
}
相关推荐
乐悠小码4 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
史努比.6 分钟前
Pod控制器
java·开发语言
程序猿麦小七14 分钟前
基于springboot的景区网页设计与实现
java·spring boot·后端·旅游·景区
敲敲敲-敲代码15 分钟前
游戏设计:推箱子【easyx图形界面/c语言】
c语言·开发语言·游戏
蓝田~22 分钟前
SpringBoot-自定义注解,拦截器
java·spring boot·后端
theLuckyLong24 分钟前
SpringBoot后端解决跨域问题
spring boot·后端·python
ROC_bird..24 分钟前
STL - vector的使用和模拟实现
开发语言·c++
.生产的驴25 分钟前
SpringCloud Gateway网关路由配置 接口统一 登录验证 权限校验 路由属性
java·spring boot·后端·spring·spring cloud·gateway·rabbitmq
小扳29 分钟前
Docker 篇-Docker 详细安装、了解和使用 Docker 核心功能(数据卷、自定义镜像 Dockerfile、网络)
运维·spring boot·后端·mysql·spring cloud·docker·容器
MavenTalk30 分钟前
Move开发语言在区块链的开发与应用
开发语言·python·rust·区块链·solidity·move