寫一個統計程序的時候,從表里查詢gateway字段因為存在空的情況,所以在定義結構體的時候,設置為sql.NullString類型。
在起一個協程去查詢到數據,然后放入到channel中,channel之前定義的是string類型的,所以需要轉換一下。
代碼實例:
package main
import (
"bufio"
"context"
"database/sql"
_"github.com/go-sql-driver/mysql"
"fmt"
"io"
"os"
"strings"
"sync"
"time"
)
var (
db *sql.DB
wg sync.WaitGroup
)
type smclog struct {
charge string
gateway sql.NullString
}
func initDB()(err error){
ctx,cancel := context.WithTimeout(context.Background(),time.Second*20)
defer cancel()
dns := "root:1234@tcp(localhost:3306)/test"
db,err = sql.Open("mysql",dns)
if err !=nil{
return err
}
err =db.PingContext(ctx)
if err !=nil{
return err
}
return nil
}
func readFile(filename string,mchan chan string){
defer wg.Done()
defer close(mchan)
file,err := os.Open(filename)
if err !=nil{
fmt.Println("open file failed err:",err)
return
}
defer file.Close()
reader := bufio.NewReader(file)
for{
line,err:= reader.ReadString('\n')
if err == io.EOF{
//這兒文件末尾有一個空行,所以不用去處理最后一行
break
}
if err !=nil{
fmt.Println("read failed:err:",err)
return
}
line =strings.TrimSuffix(line,"\n")
line =strings.TrimSpace(line)
mchan <- line
}
}
func QueryData(datachan chan string) {
defer wg.Done()
defer close(datachan)
sqlStr := "select charge,gateway from LOG202101"
stmt ,err := db.Prepare(sqlStr)
if err !=nil{
fmt.Println("prepare failed err :",err)
return
}
defer stmt.Close()
rows ,err := stmt.Query()
if err !=nil{
fmt.Println("query failed err :",err)
return
}
defer rows.Close()
for rows.Next(){
var s smclog
err := rows.Scan(&s.charge,&s.gateway)
if err !=nil{
fmt.Printf("scan failed err:%v\n",err)
return
}
datachan <- s.charge+"-"+s.gateway.String
}
}
func main() {
err := initDB()
if err !=nil{
fmt.Println("init db failed err :",err)
return
}
fmt.Println("init db success...")
mobileWb := make(chan string)
mobileFee := make(chan string)
mobileData := make(chan string)
wg.Add(3)
go readFile("./mobile.txt",mobileWb)
go readFile("./fee_mobile.txt",mobileFee)
go QueryData(mobileData)
mwb := make(map[string]int)
for v :=range mobileWb{
mwb[v] =1
}
mdb := make(map[string]string)
for v:= range mobileData{
sd := strings.Split(v,"-")
mdb[sd[0]]= sd[1]
}
//mfee :=make(map[string]int)
//for v1:=range mobileFee{
// mfee[v1]=1
//}
for k,_ := range mdb {
_,ok := mwb[k]
if ok{
data := mdb[k]
//返回網關和對應的手機號
fmt.Println(data,k)
}
}
wg.Wait()
}
