В программе есть горутина, которая запускается раз в 5 минут и кладем в БД новые данные.
В основной программе работает телеграмм бот.
Если отключить горутину, то утечки нет.
Возможно дело в коннекте с БД: связь один раз открывается в файле main.go, а дальше везде передается объект БД, который не закрывается - программа работает вечно и код не доходит до выполнения строчки закрытия соединения.
//index.go
func main(){
db, err := sql.Open("sqlite3", "test.db")
go dbWorker(db) //вызов горутины из-за которой течет память
defer db.Close()
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates:= bot.GetUpdatesChan(u)
for update := range updates {
if update.Message != nil { // If we got a message
mes=sendReply(update.Message, bot, db)
bot.Send(mes)
}
}
}
Код анонимизирован (имена переменных и полей в БД ненастоящие):
func f(rows *sql.Rows, db *sql.DB){
var unworkingDeviceInfos []DeviceInfo
for rows.Next() {
var current DeviceInfo
if err := rows.Scan(¤t.c,¤t.DeviceType,¤t.User); err != nil {
fmt.Println("Error while scanning...")
}
unworkingDeviceInfos = append(unworkingDeviceInfos, current)
}
fmt.Println("Count of unworkingDevices: ", len(unworkingDeviceInfos))
for i:=0; i<len(unworkingDeviceInfos); i++ {
current:=unworkingDeviceInfos[i]
device := NewDevice(current.c, current.DeviceLogin, current.DevicePassword, current.DeviceType)
rawJSON, err:=device.getStats()
if err==nil{
duration,err:=getDeviceDowntime(db, current.c)
if err!=nil{
log.Println("getDeviceDowntime raise error %v", err)
}
sendWakeupMessage(current.c)
if duration<=650{
info, err:=parseStats(rawJSON, current.DeviceType)
query,err:=db.Prepare("INSERT INTO reports(a,b,c,d,e,f,g,h,x,y,z) VALUES(?,?,?,?,?,?,?,?,?,?,?)")
if err!=nil{
fmt.Println("Error with inserting")
}
query.Exec(time.Now(),current.User,current.c,RESTARTING,info.c, info.f, info.d, info.e, info.x, info.y,0)
}
query,err:=db.Prepare("INSERT INTO reports(a,user,c,d,e,f,g,h,x,y,z) VALUES(?,?,?,?,?,?,?,?,?,?,?)")
if err!=nil{
fmt.Println("Error with inserting")
}
f:=0
query.Exec(time.Now(),current.User,current.c,FAIL,NORMAL, f, 0, 0, "", "",duration)
queryStr:=fmt.Sprintf("UPDATE devices SET d=0,reported=0 WHERE c='%s'",current.c)
db.Exec(queryStr)
}
}
}
func g(rows *sql.Rows, db *sql.DB){
var workingDeviceInfos []DeviceInfo
for rows.Next() {
var current DeviceInfo
if err := rows.Scan(¤t.c,¤t.DeviceType,¤t.User, ¤t.Reported); err != nil {
fmt.Println("Error while scanning...")
}
workingDeviceInfos = append(workingDeviceInfos, current)
}
for i:=0; i<len(workingDeviceInfos); i++ {
var current DeviceInfo
var Device Device
var err error
current=workingDeviceInfos[i]
Device = NewDevice(current.c, current.DeviceLogin, current.DevicePassword, current.DeviceType)
var rawJSON []byte
rawJSON, err=device.getStats()
var info UniversalStatsType
if err!=nil{
log.Println("Possible dead device: ", current.c)
if (current.Reported==0){
sendAlert(current.c, current.User)
}
date:=time.Now().Unix()
query:=fmt.Sprintf("UPDATE devices SET d=%d,failDate=%d,reported=1 WHERE c='%s'",RESTARTING,date,current.c)
db.Exec(query)
} else {
fmt.Println("Good Device")
info, err=parseStats(rawJSON, current.DeviceType)
if err!=nil{
log.Println("Error while parsing stats!")
continue
}
//Записываем
query,err:=db.Prepare("INSERT INTO reports(date,user,c,d,e,f,rt,e,x,y,z) VALUES(?,?,?,?,?,?,?,?,?,?,?)")
if err!=nil{
fmt.Println("Error with inserting")
}
query.Exec(time.Now(),current.User,current.c,info.d,info.s, info.f, info.i, info.x, info.y, info.z,0)
}
}
}
func dbWorker(db *sql.DB)error{
fmt.Println("Starting dbWorker...")
for {
if (!globalConfig.workerIsEnabled){
time.Sleep(time.Minute)
continue
}
rows, err := db.Query("SELECT a,b,c FROM table WHERE param=?",value)
if err != nil {
fmt.Println("Error 1 in dbWorker", err)
return err
}
f(rows, db)
rows.Close()
rows, err = db.Query("SELECT a,b,c,d FROM table WHERE param!=?",value)
if err != nil {
fmt.Println("Error 2 in dbWorker", err)
return err
}
g(rows, db)
rows.Close()
time.Sleep(5*time.Minute)
}
}