golang 并发请求并更新数据示例
package mainimport ("encoding/json""fmt""log""net/http""os""sync""time"_ "github.com/go-sql-driver/mysql""github.com/jmoiron/sqlx")/*CREATE TABLE `address` (`id` int(10) un...
·
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"sync"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
/*
CREATE TABLE `address` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ip` char(15) NOT NULL DEFAULT '',
`city` varchar(32) NOT NULL DEFAULT '',
`region` varchar(32) NOT NULL DEFAULT '',
`country` varchar(32) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
*/
// Address structure for table address
type Address struct {
ID int64 `db:"id"`
IP string `db:"ip"`
City string `db:"city"`
Region string `db:"region"`
Country string `db:"country"`
}
// TableName for address
func (a *Address) TableName() string {
return "address"
}
const (
dbUser = "root"
dbPasswd = "123456"
dbHost = "localhost"
dbPort = 3306
dbName = "go_test"
)
var db *sqlx.DB
func init() {
var err error
db, err = sqlx.Connect("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4,utf8", dbUser, dbPasswd, dbHost, dbPort, dbName))
if nil != err {
log.Fatalln(err)
}
}
func main() {
testHTTPResp()
processIP()
}
func processIP() {
var totalCount int64
err := db.Get(&totalCount, "SELECT COUNT(*) FROM address;")
if nil != err {
log.Fatalln(err)
os.Exit(1)
}
var pageSize int64
var offset int64
pageSize = 500
var wg sync.WaitGroup
for offset = 0; offset <= totalCount; offset += pageSize {
dataList := []Address{}
sql := fmt.Sprintf("SELECT id, ip FROM address ORDER BY id ASC LIMIT %d, %d;", offset, pageSize)
err = db.Select(&dataList, sql)
if nil != err {
log.Fatalln(err)
os.Exit(1)
}
wg.Add(len(dataList))
for _, item := range dataList {
go func(ip string, id int64) {
defer wg.Done()
if ip != "" {
var data HTTPResp
err = sendHTTPRequest(ip, &data)
if err == nil {
sql := fmt.Sprintf("UPDATE address SET city = '%s', region = '%s', country = '%s' WHERE id = %d;", data.City, data.Region, data.CountryName, id)
db.MustExec(sql)
}
}
}(item.IP, item.ID)
}
wg.Wait()
}
}
/*
https://ipapi.co/112.24.40.51/json/ 响应结构
{
"ip": "112.24.40.51",
"city": "Zhenjiang",
"region": "Jiangsu",
"region_code": "JS",
"country": "CN",
"country_name": "China",
"continent_code": "AS",
"in_eu": false,
"postal": null,
"latitude": 32.2109,
"longitude": 119.4551,
"timezone": "Asia/Shanghai",
"utc_offset": "+0800",
"country_calling_code": "+86",
"currency": "CNY",
"languages": "zh-CN,yue,wuu,dta,ug,za",
"asn": "AS56046",
"org": "China Mobile communications corporation"
}
*/
// HTTPResp structrue for response of ip query
type HTTPResp struct {
City string `json:"city"`
Region string `json:"region"`
CountryName string `json:"country_name"`
}
func sendHTTPRequest(ip string, data *HTTPResp) error {
req, _ := http.NewRequest("GET", fmt.Sprintf("https://ipapi.co/%s/json/", ip), nil)
client := http.Client{
Timeout: 10 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
err = json.NewDecoder(resp.Body).Decode(&data)
if err != nil {
return err
}
return nil
}
// 测试输出
func testHTTPResp() {
var data HTTPResp
err := sendHTTPRequest("112.24.40.51", &data)
if err != nil {
fmt.Println(err.Error())
}
fmt.Printf("test\ncity: %s, region: %s, country_name: %s\n", data.City, data.Region, data.CountryName)
}
go build -o ./getIPDetail ./main.go
./getIPDetail
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)