Too much memory usage. Appreccite any help [SOLVED]

Hey there. I’m to exited by working on that language, the only problem I’m getting is memory usage. I wrote an application that was originally written in Delphi, and that’s been working pretty good, but I need my application to be cross platform, then I wrote it in GO. Everything works perfectly fine, except memory usage. Imma put my main unit code here, and a download link to the whole project, this project is really really small, I only need to see where am I doing wrong to use so much memory, and will appreciate any help;

PROJECT DOWNLOAD LINK HERE

package main

import "net"

import "hlsat.com.br/funcoes_gerais"
import "strings"

import "database/sql"
import "time"
import "strconv"

//import "runtime"

//import "fmt"

//import "runtime/debug"

func main() {

	// carrega configuracoes iniciais e conecta no banco ---------------------------

	LoadConfig()
	db := ConectaBanco()

	// carrega configuracoes iniciais e conecta no banco ---------------------------

	// ativa o servidor udp --------------------------------------------------------

	ServerAddr, err := net.ResolveUDPAddr("udp", ":2008")
	CheckError(err)
	ServerConn, err := net.ListenUDP("udp", ServerAddr)
	CheckError(err)
	defer ServerConn.Close()
	buf := make([]byte, 1024)

	// ativa o servidor udp --------------------------------------------------------

	AtivaLiberaMemoria()

	for {

		var Dados []string
		var UltimaPosicao TPonto
		var PosicaoAtual TPonto

		var SerieModulo string
		var TipoMsg string
		var Protocolo string
		var EnviaACK bool
		var RegistraAlerta bool
		var Latitude string
		var Longitude string
		var StatusPosicao string
		var GPSValido string
		var Velocidade string
		var Ignicao string
		var Antifurto string
		var Saida1 string
		var Saida2 string
		var Saida3 string
		var Saida4 string
		var Panico string
		var Entrada1 string
		var Entrada2 string
		var Entrada3 string
		var Entrada4 string

		var Direcao string

		var VelocidadeMaximaExcedida string
		var BateriaCarregando string
		var FalhaBateriaInterna string
		var FalhaAlimentacaoPrincipal string
		var Movendo string
		var Tensao string
		var Hodometro string
		var Horimetro string

		var AlertID string
		var ibutton string

		var DataHora time.Time
		var DataHoraGPS time.Time

		var IdMotorista string
		var IdVeiculo string
		var RegistraEventosEntradas string
		var GrauAngulo int
		var FiltroGPS string
		var Rpm string

		IdMotorista = "0"

		//RECEBE OS PACOTES NO UDP -----------------------------------------------------

		n, addr, err := ServerConn.ReadFromUDP(buf)
		CheckError(err)
		Rec := strings.TrimSpace(string(buf[0:n]))

		//RECEBE OS PACOTES NO UDP -----------------------------------------------------

		Dados = strings.Split(Rec, ";")

		TipoMsg = Dados[0]

		if Dados[1] == "Res" {
			SerieModulo = Dados[2]
		} else {
			SerieModulo = Dados[1]
		}

		Protocolo = funcoes_gerais.CopyStr(Rec, 1, 5) //SA200 ou ST300

		//RESPOSTA AOS COMANDOS --------------------------------------------------------

		if Dados[1] == "Res" {
			GeraLog(Rec)
		}

		//RESPOSTA AOS COMANDOS --------------------------------------------------------

		//VERIFICA SE O MÓDULO ESTÁ CADASTRADO E ATIVO NO SISTEMA-----------------------

		var IdModulo string
		var ACK string
		err = db.QueryRow("SELECT ID, SUNTECHACK AS ACK FROM MODULOS WHERE (SERIEMODULO = ?) AND (ATIVO = 1)", SerieModulo).Scan(&IdModulo, &ACK)
		if err == sql.ErrNoRows {
			continue
		}
		EnviaACK = (ACK == "1")

		//VERIFICA SE O MÓDULO ESTÁ CADASTRADO E ATIVO NO SISTEMA-----------------------

		//ACK POSICAO-------------------------------------------------------------------

		if EnviaACK {
			enviaUDP(ServerConn, addr, Protocolo+"ACK;"+SerieModulo)
		}

		//ACK POSICAO-------------------------------------------------------------------

		if (TipoMsg == Protocolo+"STT") || (TipoMsg == Protocolo+"ALT") { //PACOTE POSICAO ou PACOTE DE ALERTA
			if Protocolo == "SA200" {
				Latitude = ajustaCordenada(Dados[6])
				Longitude = ajustaCordenada(Dados[7])
				DataHora = time.Now()
				DataHoraGPS, err = time.Parse("01/02/2006 15:04:05", extraiDataHora(Dados[3]+Dados[4]))
				if err != nil {
					GeraLog("Erro no tratamento de data; DataHoraGPS")
					continue
				}
				DataHoraGPS = funcoes_gerais.DecHour(2, DataHoraGPS)
				GrauAngulo = int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[9])))

				GPSValido = Dados[11]
				VelocidadeMaximaExcedida = "0"
				BateriaCarregando = "0"
				FalhaBateriaInterna = "0"
				FalhaAlimentacaoPrincipal = "0"
				Antifurto = "0"
				Movendo = "2" //2=NÃO DISPONÍVEL
				Velocidade = strconv.Itoa(int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[8]))))

				if Dados[13] != "0.00" {
					Tensao = Dados[13]
				} else {

					//   O OutOfRange() é porque pode ser que o rastreador esteja configurado pra não acrescentar essas informaçoes no final da string,
					//   se não tiver essas informações vai cair em exceção de "range out of bounds", se cair na exceção jogo 0.00

					if !funcoes_gerais.OutOfRange(18, Dados) {
						Tensao = Dados[18]
					} else {
						Tensao = "0.00"
					}
				}

				Ignicao = funcoes_gerais.CopyStr(Dados[14], 1, 1)
				Panico = "0"
				Entrada1 = funcoes_gerais.CopyStr(Dados[14], 2, 1)
				Entrada2 = funcoes_gerais.CopyStr(Dados[14], 3, 1)
				Entrada3 = funcoes_gerais.CopyStr(Dados[14], 4, 1)
				Entrada4 = "0"
				Saida1 = funcoes_gerais.CopyStr(Dados[14], 5, 1)
				Saida2 = funcoes_gerais.CopyStr(Dados[14], 6, 1)
				Saida3 = "0"
				Saida4 = "0"
				Hodometro = Dados[12]

				//  MODELOS MAIS ANTIGOS COMO O ST210I NÃO TÊM ESSA INFORMAÇÃO OU CASO "STT_HBM" NÃO ESTEJA CONFIGURADO,
				//  VAI CAIR EM EXCEÇÃO, JOGAR VALORES DEFAULT NO EXCEPT.

				if TipoMsg == Protocolo+"STT" {
					if !funcoes_gerais.OutOfRange(19, Dados) {
						Horimetro = Dados[17]
						StatusPosicao = Dados[19]
					} else {
						Horimetro = "0"
						StatusPosicao = "1"
					}

					if !funcoes_gerais.OutOfRange(20, Dados) {
						Rpm = Dados[20]
					} else {
						Rpm = "0"
					}

					if !funcoes_gerais.OutOfRange(21, Dados) {
						ibutton = Dados[21]
					} else {
						ibutton = ""
					}
				}

				if TipoMsg == Protocolo+"ALT" {
					AlertID = Dados[15]

					if !funcoes_gerais.OutOfRange(18, Dados) {
						Horimetro = Dados[16]
						StatusPosicao = Dados[18]
					} else {
						Horimetro = "0"
						StatusPosicao = "1"
					}

					if !funcoes_gerais.OutOfRange(19, Dados) {
						Rpm = Dados[19]
					} else {
						Rpm = "0"
					}

					if !funcoes_gerais.OutOfRange(20, Dados) {
						ibutton = Dados[20]
					} else {
						ibutton = ""
					}
				}
			} //FIM if Protocolo == "SA200" {......................................................

			if Protocolo == "ST300" {
				//ST3XXModelo = Dados[2]
				Latitude = ajustaCordenada(Dados[7])
				Longitude = ajustaCordenada(Dados[8])
				DataHora = time.Now()
				DataHoraGPS, err = time.Parse("01/02/2006 15:04:05", extraiDataHora(Dados[4]+Dados[5]))
				if err != nil {
					GeraLog("Erro no tratamento de data; DataHoraGPS(ST300).")
					continue
				}
				DataHoraGPS = funcoes_gerais.DecHour(2, DataHoraGPS) //AJUSTA O FUSO HORARIO.
				GrauAngulo = int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[10])))
				GPSValido = Dados[12]
				VelocidadeMaximaExcedida = "0"
				BateriaCarregando = "0"
				FalhaBateriaInterna = "0"
				FalhaAlimentacaoPrincipal = "0"
				Antifurto = "0"
				Movendo = "2" //2=NÃO DISPONÍVEL
				Velocidade = strconv.Itoa(int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[9]))))
				//Velocidade = strconv.Itoa(fmt.Printf("%03d", int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[9])))))

				if Dados[14] != "0.00" {
					Tensao = Dados[14]
				} else {

					//   O OutOfRange() é porque pode ser que o rastreador esteja configurado pra não acrescentar essas informaçoes no final da string,
					//   se não tiver essas informações vai cair em exceção de "range out of bounds", se cair na exceção jogo 0.00

					if !funcoes_gerais.OutOfRange(19, Dados) {
						Tensao = Dados[19]
					} else {
						Tensao = "0.00"
					}
				}

				Ignicao = funcoes_gerais.CopyStr(Dados[15], 1, 1)
				Panico = "0"
				Entrada1 = funcoes_gerais.CopyStr(Dados[15], 2, 1)
				Entrada2 = funcoes_gerais.CopyStr(Dados[15], 3, 1)
				Entrada3 = funcoes_gerais.CopyStr(Dados[15], 4, 1)
				Entrada4 = "0"
				Saida1 = funcoes_gerais.CopyStr(Dados[15], 5, 1)
				Saida2 = funcoes_gerais.CopyStr(Dados[15], 6, 1)
				Saida3 = "0"
				Saida4 = "0"
				Hodometro = Dados[13]

				//  MODELOS MAIS ANTIGOS COMO O ST210I NÃO TÊM ESSA INFORMAÇÃO OU CASO "STT_HBM" NÃO ESTEJA CONFIGURADO,
				//  VAI CAIR EM EXCEÇÃO, JOGAR VALORES DEFAULT NO EXCEPT.

				if TipoMsg == Protocolo+"STT" {
					if !funcoes_gerais.OutOfRange(20, Dados) {
						Horimetro = Dados[18]
						StatusPosicao = Dados[20]
					} else {
						Horimetro = "0"
						StatusPosicao = "1"
					}

					if !funcoes_gerais.OutOfRange(21, Dados) {
						Rpm = Dados[21]
					} else {
						Rpm = "0"
					}

					if !funcoes_gerais.OutOfRange(22, Dados) {
						ibutton = Dados[22]
					} else {
						ibutton = ""
					}
				}

				if TipoMsg == Protocolo+"ALT" {
					AlertID = Dados[16]

					if !funcoes_gerais.OutOfRange(19, Dados) {
						Horimetro = Dados[17]
						StatusPosicao = Dados[19]
					} else {
						Horimetro = "0"
						StatusPosicao = "1"
					}

					if !funcoes_gerais.OutOfRange(20, Dados) {
						Rpm = Dados[20]
					} else {
						Rpm = "0"
					}

					if !funcoes_gerais.OutOfRange(21, Dados) {
						ibutton = Dados[21]
					} else {
						ibutton = ""
					}
				}
			} //FIM if Protocolo == "ST300" {......................................................

			//Compatibilizando no banco com o StatusPosicao do "SmartCar", mostra se a posição é atualizada ou da memória.
			if StatusPosicao == "1" {
				StatusPosicao = "2" //Atualizada
			}
			if StatusPosicao == "0" {
				StatusPosicao = "3" //Memória
			}
			//Compatibilizando no banco com o StatusPosicao do "SmartCar", mostra se a posição é atualizada ou da memória.

			if Ignicao == "1" {
				Ignicao = "L"
			} else {
				Ignicao = "0"
			}

			if ((GrauAngulo >= 0) && (GrauAngulo <= 24)) || ((GrauAngulo >= 326) && (GrauAngulo <= 360)) {
				Direcao = "N"
			}
			if (GrauAngulo >= 25) && (GrauAngulo <= 65) {
				Direcao = "NE"
			}
			if (GrauAngulo >= 66) && (GrauAngulo <= 134) {
				Direcao = "E"
			}
			if (GrauAngulo >= 135) && (GrauAngulo <= 165) {
				Direcao = "SE"
			}
			if (GrauAngulo >= 166) && (GrauAngulo <= 205) {
				Direcao = "S"
			}
			if (GrauAngulo >= 206) && (GrauAngulo <= 245) {
				Direcao = "SW"
			}
			if (GrauAngulo >= 246) && (GrauAngulo <= 295) {
				Direcao = "W"
			}
			if (GrauAngulo >= 296) && (GrauAngulo <= 325) {
				Direcao = "NW"
			}

			// FILTRA POSIÇÕES COM COORDENADAS IGUAIS OU MAIORES QUE ZERO, NO BRASIL
			//SÓ EXISTEM COORDENADAS NEGATIVAS. EVITANDO POSIÇÕES INDESEJADAS LÁ NA ÁFRICA/INGLATERRA
			if (funcoes_gerais.StrToFloat(Latitude) >= 0) || (funcoes_gerais.StrToFloat(Longitude) >= 0) {
				continue
			}
			// FILTRA POSIÇÕES COM COORDENADAS IGUAIS OU MAIORES QUE ZERO, NO BRASIL
			//SÓ EXISTEM COORDENADAS NEGATIVAS. EVITANDO POSIÇÕES INDESEJADAS LÁ NA ÁFRICA/INGLATERRA

			//PEGA O ID DO VEÍCULO----------------------------------------------------------

			err = db.QueryRow("SELECT IDVEICULO, REGISTRAEVENTOSENTRADAS, FILTROGPS FROM VWVEICULOSCLIENTE WHERE SERIEMODULO = ?", SerieModulo).Scan(&IdVeiculo, &RegistraEventosEntradas, &FiltroGPS)
			if err == sql.ErrNoRows {
				continue
			}

			//PEGA O ID DO VEÍCULO----------------------------------------------------------

			//PEGA O ID DO MOTORISTA CASO HAJA IDENTIFICACAO--------------------------------

			if (strings.TrimSpace(ibutton) != "") && (strings.TrimSpace(ibutton) != "00000000000000") {
				err = db.QueryRow("SELECT ID AS IDMOTORISTA FROM MOTORISTAS WHERE (IDELETRONICO = ?) OR (IDELETRONICORESERVA = ?)", ibutton, ibutton).Scan(&IdMotorista)
				if err != nil {
					IdMotorista = "0"
					GeraLog(err.Error())
				}
			}

			//PEGA O ID DO MOTORISTA CASO HAJA IDENTIFICACAO--------------------------------

			//COMANDOS PARA O MÓDULO--------------------------------------------------------

			var SetBloqueioSireneOn string
			var SetDesbloqueioSireneOff string
			var SetBloqueio string
			var SetDesbloqueio string
			var SetSireneOn string
			var SetSireneOff string
			var SetReset string
			var SetHorimetro string
			var SetLimpaMemoria string
			var GetMotoristas string
			var SetComandoGenerico string

			sqlcmd := "SELECT BLOQUEIOSIRENEON,DESBLOQUEIOSIRENEOFF,BLOQUEIO,DESBLOQUEIO,SIRENEON,SIRENEOFF,RESET," +
				"HORIMETRO,LIMPAMEMORIA,GETMOTORISTAS,COMANDOGENERICO FROM VWCOMANDOS WHERE SERIEMODULO = ?"
			err = db.QueryRow(sqlcmd, SerieModulo).Scan(&SetBloqueioSireneOn, &SetDesbloqueioSireneOff, &SetBloqueio, &SetDesbloqueio, &SetSireneOn, &SetSireneOff, &SetReset, &SetHorimetro, &SetLimpaMemoria, &GetMotoristas, &SetComandoGenerico)
			if err != nil {
				GeraLog(err.Error())
			} else {
				if (SetBloqueioSireneOn == "1") && (funcoes_gerais.StrToInt64(Velocidade) <= 30) {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Enable1")
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Enable2")
				}

				if SetDesbloqueioSireneOff == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Disable1")
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Disable2")
				}

				if (SetBloqueio == "1") && (funcoes_gerais.StrToInt64(Velocidade) <= 30) {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Enable1")
				}

				if SetDesbloqueio == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Disable1")
				}

				if SetSireneOn == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Enable2")
				}

				if SetSireneOff == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Disable2")
				}

				if SetReset == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Reboot")
				}

				if SetHorimetro != "-1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;SetHMeter="+SetHorimetro)
				}

				if SetLimpaMemoria == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;EraseAll")
				}

				if GetMotoristas == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"HGD;"+SerieModulo+";02;ALL")
				}

				if SetComandoGenerico != "-1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;"+SetComandoGenerico)
				}
			}

			//COMANDOS PARA O MÓDULO--------------------------------------------------------

			//EM CASO DE ALERTA, INSERE NO REGISTRO DE ALERTAS ENVIO DO SMS E RELATÓRIO-----
			if TipoMsg == Protocolo+"ALT" {

				var EventoAlerta string
				var TipoRelatorioAlerta string

				switch funcoes_gerais.StrToInt64(AlertID) {
				case 01:
					{
						RegistraAlerta = true
						EventoAlerta = "VELOCIDADE MÁXIMA EXCEDIDA."
						TipoRelatorioAlerta = "3"
					}
				case 03:
					{
						RegistraAlerta = true
						EventoAlerta = "ANTENA GPS DESCONECTADA."
						TipoRelatorioAlerta = "4"
					}
				case 16:
					{
						RegistraAlerta = true
						EventoAlerta = "ENTROU EM COLISAO."
						TipoRelatorioAlerta = "7"
					}
				case 41:
					{
						RegistraAlerta = true
						EventoAlerta = "FALHA NA ALIMENTACAO PRINCIPAL."
						TipoRelatorioAlerta = "6"
					}
				case 45:
					{
						RegistraAlerta = true
						EventoAlerta = "BATERIA INTERNA DE BACKUP REMOVIDA."
						TipoRelatorioAlerta = "5"
					}
				case 59:
					{
						RegistraAlerta = true
						EventoAlerta = "MOTORISTA IDENTIFICADO."
						TipoRelatorioAlerta = "8"
					}
				}

				if RegistraAlerta == true {
					LocalizacaoAlerta := RetornaEndereco(Latitude, Longitude)

					sqlcmd := " INSERT INTO REGISTROSALERTAS (IDVEICULO, IDMOTORISTA, DATAHORA, EVENTO, LOCALIZACAO, TIPORELATORIO, ALERTAENVIADO, VELOCIDADE, MOVENDO) " +
						" VALUES (" + IdVeiculo + ", " + IdMotorista + ", CONVERT(DATETIME, '" + DataHoraGPS.Format("2006-01-02 15:04:05") + ".000', 121), '" + EventoAlerta + "', '" + LocalizacaoAlerta + "', " + TipoRelatorioAlerta + ", 0, '" + Velocidade + "', '" + Movendo + "') "
					stmt, err := db.Prepare(sqlcmd)
					if err != nil {
						GeraLog("Registros Alertas,erro prepare: " + err.Error())
						continue
					}

					res, err := stmt.Exec()
					if err != nil {
						GeraLog("Registros Alertas,erro stmt.Exec(): " + err.Error())
						continue
					}

					rowCnt, err := res.RowsAffected()
					if err != nil {
						GeraLog("Registros Alertas; Erro ao tentar inserir. Registros Afetados: " + strconv.FormatInt(rowCnt, 10) + ".\r\n" + err.Error())
						continue
					}
				}
			}
			//EM CASO DE ALERTA, INSERE NO REGISTRO DE ALERTAS ENVIO DO SMS E RELATÓRIO-----

			//PEGA ULTIMA POSICAO OU REGISTRA O MODULO CASO NAO SEJA ENCONTRADO-------------

			if ModuloNaoRegistrado(SerieModulo) {
				ArrUltimaPosicao = append(ArrUltimaPosicao, TUltimaPosicao{funcoes_gerais.StrToFloat(Latitude), funcoes_gerais.StrToFloat(Longitude), SerieModulo})
			} else {
				UltimaPosicao = RetornaUltimaPosicao(SerieModulo)
				PosicaoAtual = TPonto{funcoes_gerais.StrToFloat(Latitude), funcoes_gerais.StrToFloat(Longitude)}

				if DentroPerimetroUltimaPosicao(UltimaPosicao, PosicaoAtual) || ((FiltroGPS == "1") && (Ignicao == "0")) {
					Latitude = funcoes_gerais.FloatToStr(UltimaPosicao.Lat)
					Longitude = funcoes_gerais.FloatToStr(UltimaPosicao.Lng)
				}

				AtualizaUltimaPosicao(funcoes_gerais.StrToFloat(Latitude), funcoes_gerais.StrToFloat(Longitude), SerieModulo)
			}

			//PEGA ULTIMA POSICAO OU REGISTRA O MODULO CASO NAO SEJA ENCONTRADO-------------

			var Modelo string

			if Protocolo == "SA200" {
				Modelo = "STT2XX"
			}
			if Protocolo == "ST300" {
				Modelo = "STT3XX"
			}

			//INSERE NA TABELA DE ATUALZACOES-----------------------------------------------

			sqlcmdatualizacao := " INSERT INTO ATUALIZACOES (STATUSPOSICAO, TIPOMSG, STATUSGPS, DATAHORA, DATAHORAGPS, LONGITUDE, LATITUDE, VELOCIDADE, IDMODULO, IGNICAO, ANTIFURTO, SAIDAS1, SAIDAS2, PANICO, ENTRADAS1, ENTRADAS2, ENTRADAS3, ENTRADAS4, SAIDAS3, SAIDAS4, DIRECAO, VELOCIDADEMAXIMAEXCEDIDA, BATERIACARREGANDO, FALHABATERIAINTERNA, FALHAALIMENTACAOPRINCIPAL, MOVENDO, TENSAO, HODOMETRO, HORIMETRO, RPM, INDICEPOSICAOMXT, MODELO, IDMOTORISTA) VALUES ('" + StatusPosicao + "', '4', '" + GPSValido + "', CONVERT(DATETIME, '" + DataHora.Format("2006-01-02 15:04:05") + ".000', 121), CONVERT(DATETIME, '" + DataHoraGPS.Format("2006-01-02 15:04:05") + ".000', 121), '" + Longitude + "', '" + Latitude + "', '" + Velocidade + "', " + IdModulo + ", '" + Ignicao + "', '" + Antifurto + "', '" + Saida1 + "', '" + Saida2 + "', '" + Panico + "', '" + Entrada1 + "', '" + Entrada2 + "', '" + Entrada3 + "', '" + Entrada4 + "', '" + Saida3 + "', '" + Saida4 + "', '" + Direcao + "', '" + VelocidadeMaximaExcedida + "', '" + BateriaCarregando + "', '" + FalhaBateriaInterna + "', '" + FalhaAlimentacaoPrincipal + "', '" + Movendo + "', '" + Tensao + "', " + Hodometro + ", " + Horimetro + ", " + Rpm + ", '0', '" + Modelo + "', " + IdMotorista + ") "
			stmt, err := db.Prepare(sqlcmdatualizacao)
			defer stmt.Close()
			if err != nil {
				GeraLog("Insert Atualizacoes; erro prepare: " + err.Error())
				continue
			}

			res, err := stmt.Exec()

			if err != nil {
				GeraLog("Insert Atualizacoes; erro stmt.Exec(): " + err.Error())
				GeraLog(sqlcmdatualizacao)
				continue
			}

			rowCnt, err := res.RowsAffected()
			if err != nil {
				GeraLog("Erro ao tentar inserir. Registros Afetados: " + strconv.FormatInt(rowCnt, 10) + ".\r\n" + err.Error())
			}

			//INSERE NA TABELA DE ATUALZACOES-----------------------------------------------

		} //FIM if (TipoMsg == Protocolo+"STT") || (TipoMsg == Protocolo+"ALT") {........

		if (TipoMsg == Protocolo+"CMD") || ((TipoMsg == Protocolo+"HGD") && (Dados[1] == "Res")) { //ACK vinda do rastreador
			//RECEBEU CONFIRMAÇÃO DO MÓDULO, ENTÃO RESETA TODOS OS COMANDOS SETANDO "0" E SETA RESPOSTA = "1"-----

			sqlresetcomandos := " UPDATE COMANDOS SET COMANDOGENERICO='-1', GETMOTORISTAS=0, BLOQUEIO=0, BLOQUEIOPROGRESSIVO=0, BLOQUEIOSIRENEON=0, DESBLOQUEIO=0, DESBLOQUEIOSIRENEOFF=0, SIRENEON=0, SIRENEOFF=0, NUM1=0, NUM2=0, NUM3=0, NUM4=0, LEDRED=0, LEDGREEN=0, LEDX=0, " +
				" RESPOSTA=1, INTERVALO=0, PANICO=0, RESET=0, DESATIVAFILTROGPS=0, ATIVAFILTROGPS=0, POWEROFF=0, LIMPAMEMORIA=0, HORIMETRO='-1', CONFIGIP='-1' " +
				" WHERE IDMODULO = (SELECT ID FROM MODULOS WHERE SERIEMODULO = ?) "
			stmt, err := db.Prepare(sqlresetcomandos)
			defer stmt.Close()
			if err != nil {
				GeraLog("Update reset comandos; erro prepare: " + err.Error())
				continue
			}

			res, err := stmt.Exec(SerieModulo)

			if err != nil {
				GeraLog("Update reset comandos; erro stmt.Exec(): " + err.Error())
				GeraLog(sqlresetcomandos)
				continue
			}

			rowCnt, err := res.RowsAffected()
			if err != nil {
				GeraLog("Erro ao tentar efeturar o UPDATE na tabela comandos. Registros Afetados: " + strconv.FormatInt(rowCnt, 10) + ".\r\n" + err.Error())
			}

			//RECEBEU CONFIRMAÇÃO DO MÓDULO, ENTÃO RESETA TODOS OS COMANDOS SETANDO "0" E SETA RESPOSTA = "1"-----
		}

		//debug.FreeOSMemory() //GARBAGE COLLECT
	} //FIM LOOP SERVICO UDP..........................
}

Thanks.

The first thing I’d do is move the declarations beginning at line 42 and again at line 409 in main.go outside of the for{…} loop. See what happens to your memory usage then.

1 Like

tldr; at first sight you created new variables at every iteration of that loop and that’s bad.

1 Like

Thaks guys. I was thinking of those vars too, I’m used to Delphi, little bit different, that’s why I’m so confused about a lot of things. What about changing “:=” to declarations outside also?

about declarations:

1 Like

May be Inside this code, there is something wrong making this abusive memory usage?

package funcoes_gerais

import (
	"strconv"
	"strings"

	"math"
	"path/filepath"
	"reflect"
	"time"
	"unicode"

	"golang.org/x/text/transform"
	"golang.org/x/text/unicode/norm"
)

func ExtractFileName(str string) string {
	return filepath.Base(str)
}

func FloatToStr(input_num float64) string {
	// to convert a float number to a string
	return strconv.FormatFloat(input_num, 'f', -1, 64)
}

func StrToFloat(strnum string) float64 {
	Rst, _ := strconv.ParseFloat(strnum, 64)
	return Rst //strconv.ParseFloat(strnum, 64)
}

func StrToInt64(strnum string) int64 {
	Rst, _ := strconv.ParseInt(strnum, 10, 64)
	return Rst
}

func CopyStr(str string, idx int, lht int) string {
	if ((idx - 1) + lht) > len(str) {
		return str
	} else {
		return str[(idx - 1) : (idx-1)+lht]
	}
}

func ReplaceStr(str string, find string, replace string) string {
	return strings.Replace(str, find, replace, -1)
}

func isMn(r rune) bool {
	return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks
}

func RetiraAcentuacao(str string) string {
	b := make([]byte, len(str))

	t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC)
	_, _, e := t.Transform(b, []byte(str), true)
	if e != nil {
		panic(e)
	}

	return string(b)
}

func StrPos(find string, str string) int {
	i := strings.Index(str, find) + 1
	return i //utf8.RuneCountInString(str[:i])
}

func DelaySec(n time.Duration) {
	time.Sleep(n * time.Second)
}

func Round(f float64) float64 {
	return math.Floor(f + .5)
}

func OutOfRange(idx int, arr interface{}) bool {
	it := reflect.ValueOf(arr)
	if (idx + 1) > it.Len() {
		return true
	} else {
		return false
	}
}

func DecHour(hr int, dt time.Time) time.Time {
	return dt.Add(-((60 * time.Duration(hr)) * time.Minute))
}

Specially this function;

func OutOfRange(idx int, arr interface{}) bool {
	it := reflect.ValueOf(arr)
	if (idx + 1) > it.Len() {
		return true
	} else {
		return false
	}
}

Thanks again.

I only see functions, but the problem may be in how you are using them, for more in-depth details on syntax, code style, duplication I recommend:

Why do you use so many helper function? OutOfRange = len(arr) <= idx

And that big pile of spaghetti code makes it quite hard to maintain - please arrange common code into functions!

By the way, profiling your code (https://dave.cheney.net/2014/10/22/simple-profiling-package-moved-updated) will show where those allocations are coming from.

The difference between := and var = is not much, see https://dave.cheney.net/2016/12/15/declaration-scopes-in-go
But as a rule ot thumb, declare your variables as close to first usage as possible!

I use that OutOfRange because I haven’t seen any way to validate if that index exists, that array has various sizes. If you know a better way of doing that, then show me! That’s why I’m on here, to learn…

Go has “len” as a built-in function for slices:
You can replace

if !funcoes_gerais.OutOfRange(18, Dados) {
	Tensao = Dados[18]
} else {
	Tensao = "0.00"
}

with

if len(Dados) > 18 {
	Tensao = Dados[18]
} else {
	Tensao = "0.00"
}

I modified it but as I expected that’s still not the problem.

PS: I removed EVERYTHING from my code, every sql statement or connection, variables are now declared outside the for loop, and it still increases memory usage…

Any other thing to do?

I’m really getting frustrated about it because I’m having that problem with only 40 clients sending datagrams, whatif it was a thousand? That is the real expectation…

The same code written in Delphi, in the same server, same port, using the same database, same clients, same all… Look at the print below, that was started by now but, if you go there a week later, you’ll see the same memory and CPU usage. I liked GO lang but, how to really use it in real world if only by blowing on it, it increases memory usage?

make sure you didn’t miss any := declaration in the loop.

I did, I took off them all, but it still increases much memory… What I saw in some examples was that db.QueryRow() got no Close() method, like db.Query() has… 2 examples below;

Usual db.Query()

var ( id int name string ) rows, err := db.Query("select id, name from users where id = ?", 1) if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { err := rows.Scan(&id, &name) if err != nil { log.Fatal(err) } log.Println(id, name) } err = rows.Err() if err != nil { log.Fatal(err) }

db.QueryRow() example

var name string
err = db.QueryRow("select name from users where id = ?", 1).Scan(&name)
if err != nil {
	log.Fatal(err)
}
fmt.Println(name)

Tnx.

Main code is lie that now;

package main

import "net"

import "hlsat.com.br/funcoes_gerais"
import "strings"

import "database/sql"
import "time"
import "strconv"

//import "runtime"

//import "fmt"

//import "runtime/debug"

func main() {

	// carrega configuracoes iniciais e conecta no banco ---------------------------

	LoadConfig()
	db := ConectaBanco()

	// carrega configuracoes iniciais e conecta no banco ---------------------------

	// ativa o servidor udp --------------------------------------------------------

	ServerAddr, udperr := net.ResolveUDPAddr("udp", ":2008")
	CheckError(udperr)
	ServerConn, connerr := net.ListenUDP("udp", ServerAddr)
	CheckError(connerr)
	defer ServerConn.Close()
	buf := make([]byte, 1024)

	// ativa o servidor udp --------------------------------------------------------

	//AtivaLiberaMemoria()

	var Dados []string
	var UltimaPosicao TPonto
	var PosicaoAtual TPonto

	var SerieModulo string
	var TipoMsg string
	var Protocolo string
	var EnviaACK bool
	var RegistraAlerta bool
	var Latitude string
	var Longitude string
	var StatusPosicao string
	var GPSValido string
	var Velocidade string
	var Ignicao string
	var Antifurto string
	var Saida1 string
	var Saida2 string
	var Saida3 string
	var Saida4 string
	var Panico string
	var Entrada1 string
	var Entrada2 string
	var Entrada3 string
	var Entrada4 string

	var Direcao string

	var VelocidadeMaximaExcedida string
	var BateriaCarregando string
	var FalhaBateriaInterna string
	var FalhaAlimentacaoPrincipal string
	var Movendo string
	var Tensao string
	var Hodometro string
	var Horimetro string

	var AlertID string
	var ibutton string

	var DataHora time.Time
	var DataHoraGPS time.Time

	var IdMotorista string
	var IdVeiculo string
	var RegistraEventosEntradas string
	var GrauAngulo int
	var FiltroGPS string
	var Rpm string

	var SetBloqueioSireneOn string
	var SetDesbloqueioSireneOff string
	var SetBloqueio string
	var SetDesbloqueio string
	var SetSireneOn string
	var SetSireneOff string
	var SetReset string
	var SetHorimetro string
	var SetLimpaMemoria string
	var GetMotoristas string
	var SetComandoGenerico string

	var n int
	var addr *net.UDPAddr
	var err error
	var Rec string
	var sqlcmd string

	var LocalizacaoAlerta string

	var stmt *sql.Stmt

	var sqlres sql.Result

	var rowCnt int64
	for {

		IdMotorista = "0"

		SetBloqueioSireneOn = ""
		SetDesbloqueioSireneOff = ""
		SetBloqueio = ""
		SetDesbloqueio = ""
		SetSireneOn = ""
		SetSireneOff = ""
		SetReset = ""
		SetHorimetro = ""
		SetLimpaMemoria = ""
		GetMotoristas = ""
		SetComandoGenerico = ""

		//RECEBE OS PACOTES NO UDP -----------------------------------------------------

		n, addr, err = ServerConn.ReadFromUDP(buf)
		CheckError(err)
		Rec = strings.TrimSpace(string(buf[0:n]))

		//RECEBE OS PACOTES NO UDP -----------------------------------------------------

		Dados = strings.Split(Rec, ";")

		TipoMsg = Dados[0]

		if Dados[1] == "Res" {
			SerieModulo = Dados[2]
		} else {
			SerieModulo = Dados[1]
		}

		Protocolo = funcoes_gerais.CopyStr(Rec, 1, 5) //SA200 ou ST300

		//RESPOSTA AOS COMANDOS --------------------------------------------------------

		if Dados[1] == "Res" {
			GeraLog(Rec)
		}

		//RESPOSTA AOS COMANDOS --------------------------------------------------------

		//VERIFICA SE O MÓDULO ESTÁ CADASTRADO E ATIVO NO SISTEMA-----------------------

		var IdModulo string
		var ACK string
		err = db.QueryRow("SELECT ID, SUNTECHACK AS ACK FROM MODULOS WHERE (SERIEMODULO = ?) AND (ATIVO = 1)", SerieModulo).Scan(&IdModulo, &ACK)
		if err == sql.ErrNoRows {
			continue
		}
		EnviaACK = (ACK == "1")

		//VERIFICA SE O MÓDULO ESTÁ CADASTRADO E ATIVO NO SISTEMA-----------------------

		//ACK POSICAO-------------------------------------------------------------------

		if EnviaACK {
			enviaUDP(ServerConn, addr, Protocolo+"ACK;"+SerieModulo)
		}

		//ACK POSICAO-------------------------------------------------------------------

		if (TipoMsg == Protocolo+"STT") || (TipoMsg == Protocolo+"ALT") { //PACOTE POSICAO ou PACOTE DE ALERTA
			if Protocolo == "SA200" {
				Latitude = ajustaCordenada(Dados[6])
				Longitude = ajustaCordenada(Dados[7])
				DataHora = time.Now()
				DataHoraGPS, err = time.Parse("01/02/2006 15:04:05", extraiDataHora(Dados[3]+Dados[4]))
				if err != nil {
					GeraLog("Erro no tratamento de data; DataHoraGPS")
					continue
				}
				DataHoraGPS = funcoes_gerais.DecHour(2, DataHoraGPS)
				GrauAngulo = int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[9])))

				GPSValido = Dados[11]
				VelocidadeMaximaExcedida = "0"
				BateriaCarregando = "0"
				FalhaBateriaInterna = "0"
				FalhaAlimentacaoPrincipal = "0"
				Antifurto = "0"
				Movendo = "2" //2=NÃO DISPONÍVEL
				Velocidade = strconv.Itoa(int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[8]))))

				if Dados[13] != "0.00" {
					Tensao = Dados[13]
				} else {

					//   O funcoes_gerais.OutOfRange() é porque pode ser que o rastreador esteja configurado pra não acrescentar essas informaçoes no final da string,
					//   se não tiver essas informações vai cair em exceção de "range out of bounds", se cair na exceção jogo 0.00

					if !funcoes_gerais.OutOfRange(18, Dados) {
						Tensao = Dados[18]
					} else {
						Tensao = "0.00"
					}
				}

				Ignicao = funcoes_gerais.CopyStr(Dados[14], 1, 1)
				Panico = "0"
				Entrada1 = funcoes_gerais.CopyStr(Dados[14], 2, 1)
				Entrada2 = funcoes_gerais.CopyStr(Dados[14], 3, 1)
				Entrada3 = funcoes_gerais.CopyStr(Dados[14], 4, 1)
				Entrada4 = "0"
				Saida1 = funcoes_gerais.CopyStr(Dados[14], 5, 1)
				Saida2 = funcoes_gerais.CopyStr(Dados[14], 6, 1)
				Saida3 = "0"
				Saida4 = "0"
				Hodometro = Dados[12]

				//  MODELOS MAIS ANTIGOS COMO O ST210I NÃO TÊM ESSA INFORMAÇÃO OU CASO "STT_HBM" NÃO ESTEJA CONFIGURADO,
				//  VAI CAIR EM EXCEÇÃO, JOGAR VALORES DEFAULT NO EXCEPT.

				if TipoMsg == Protocolo+"STT" {
					if !funcoes_gerais.OutOfRange(19, Dados) {
						Horimetro = Dados[17]
						StatusPosicao = Dados[19]
					} else {
						Horimetro = "0"
						StatusPosicao = "1"
					}

					if !funcoes_gerais.OutOfRange(20, Dados) {
						Rpm = Dados[20]
					} else {
						Rpm = "0"
					}

					if !funcoes_gerais.OutOfRange(21, Dados) {
						ibutton = Dados[21]
					} else {
						ibutton = ""
					}
				}

				if TipoMsg == Protocolo+"ALT" {
					AlertID = Dados[15]

					if !funcoes_gerais.OutOfRange(18, Dados) {
						Horimetro = Dados[16]
						StatusPosicao = Dados[18]
					} else {
						Horimetro = "0"
						StatusPosicao = "1"
					}

					if !funcoes_gerais.OutOfRange(19, Dados) {
						Rpm = Dados[19]
					} else {
						Rpm = "0"
					}

					if !funcoes_gerais.OutOfRange(20, Dados) {
						ibutton = Dados[20]
					} else {
						ibutton = ""
					}
				}
			} //FIM if Protocolo == "SA200" {......................................................

			if Protocolo == "ST300" {
				//ST3XXModelo = Dados[2]
				Latitude = ajustaCordenada(Dados[7])
				Longitude = ajustaCordenada(Dados[8])
				DataHora = time.Now()
				DataHoraGPS, err = time.Parse("01/02/2006 15:04:05", extraiDataHora(Dados[4]+Dados[5]))
				if err != nil {
					GeraLog("Erro no tratamento de data; DataHoraGPS(ST300).")
					continue
				}
				DataHoraGPS = funcoes_gerais.DecHour(2, DataHoraGPS) //AJUSTA O FUSO HORARIO.
				GrauAngulo = int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[10])))
				GPSValido = Dados[12]
				VelocidadeMaximaExcedida = "0"
				BateriaCarregando = "0"
				FalhaBateriaInterna = "0"
				FalhaAlimentacaoPrincipal = "0"
				Antifurto = "0"
				Movendo = "2" //2=NÃO DISPONÍVEL
				Velocidade = strconv.Itoa(int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[9]))))
				//Velocidade = strconv.Itoa(fmt.Printf("%03d", int(funcoes_gerais.Round(funcoes_gerais.StrToFloat(Dados[9])))))

				if Dados[14] != "0.00" {
					Tensao = Dados[14]
				} else {

					//   O funcoes_gerais.OutOfRange() é porque pode ser que o rastreador esteja configurado pra não acrescentar essas informaçoes no final da string,
					//   se não tiver essas informações vai cair em exceção de "range out of bounds", se cair na exceção jogo 0.00

					if !funcoes_gerais.OutOfRange(19, Dados) {
						Tensao = Dados[19]
					} else {
						Tensao = "0.00"
					}
				}

				Ignicao = funcoes_gerais.CopyStr(Dados[15], 1, 1)
				Panico = "0"
				Entrada1 = funcoes_gerais.CopyStr(Dados[15], 2, 1)
				Entrada2 = funcoes_gerais.CopyStr(Dados[15], 3, 1)
				Entrada3 = funcoes_gerais.CopyStr(Dados[15], 4, 1)
				Entrada4 = "0"
				Saida1 = funcoes_gerais.CopyStr(Dados[15], 5, 1)
				Saida2 = funcoes_gerais.CopyStr(Dados[15], 6, 1)
				Saida3 = "0"
				Saida4 = "0"
				Hodometro = Dados[13]

				//  MODELOS MAIS ANTIGOS COMO O ST210I NÃO TÊM ESSA INFORMAÇÃO OU CASO "STT_HBM" NÃO ESTEJA CONFIGURADO,
				//  VAI CAIR EM EXCEÇÃO, JOGAR VALORES DEFAULT NO EXCEPT.

				if TipoMsg == Protocolo+"STT" {
					if !funcoes_gerais.OutOfRange(20, Dados) {
						Horimetro = Dados[18]
						StatusPosicao = Dados[20]
					} else {
						Horimetro = "0"
						StatusPosicao = "1"
					}

					if !funcoes_gerais.OutOfRange(21, Dados) {
						Rpm = Dados[21]
					} else {
						Rpm = "0"
					}

					if !funcoes_gerais.OutOfRange(22, Dados) {
						ibutton = Dados[22]
					} else {
						ibutton = ""
					}
				}

				if TipoMsg == Protocolo+"ALT" {
					AlertID = Dados[16]

					if !funcoes_gerais.OutOfRange(19, Dados) {
						Horimetro = Dados[17]
						StatusPosicao = Dados[19]
					} else {
						Horimetro = "0"
						StatusPosicao = "1"
					}

					if !funcoes_gerais.OutOfRange(20, Dados) {
						Rpm = Dados[20]
					} else {
						Rpm = "0"
					}

					if !funcoes_gerais.OutOfRange(21, Dados) {
						ibutton = Dados[21]
					} else {
						ibutton = ""
					}
				}
			} //FIM if Protocolo == "ST300" {......................................................

			//Compatibilizando no banco com o StatusPosicao do "SmartCar", mostra se a posição é atualizada ou da memória.
			if StatusPosicao == "1" {
				StatusPosicao = "2" //Atualizada
			}
			if StatusPosicao == "0" {
				StatusPosicao = "3" //Memória
			}
			//Compatibilizando no banco com o StatusPosicao do "SmartCar", mostra se a posição é atualizada ou da memória.

			if Ignicao == "1" {
				Ignicao = "L"
			} else {
				Ignicao = "0"
			}

			if ((GrauAngulo >= 0) && (GrauAngulo <= 24)) || ((GrauAngulo >= 326) && (GrauAngulo <= 360)) {
				Direcao = "N"
			}
			if (GrauAngulo >= 25) && (GrauAngulo <= 65) {
				Direcao = "NE"
			}
			if (GrauAngulo >= 66) && (GrauAngulo <= 134) {
				Direcao = "E"
			}
			if (GrauAngulo >= 135) && (GrauAngulo <= 165) {
				Direcao = "SE"
			}
			if (GrauAngulo >= 166) && (GrauAngulo <= 205) {
				Direcao = "S"
			}
			if (GrauAngulo >= 206) && (GrauAngulo <= 245) {
				Direcao = "SW"
			}
			if (GrauAngulo >= 246) && (GrauAngulo <= 295) {
				Direcao = "W"
			}
			if (GrauAngulo >= 296) && (GrauAngulo <= 325) {
				Direcao = "NW"
			}

			// FILTRA POSIÇÕES COM COORDENADAS IGUAIS OU MAIORES QUE ZERO, NO BRASIL
			//SÓ EXISTEM COORDENADAS NEGATIVAS. EVITANDO POSIÇÕES INDESEJADAS LÁ NA ÁFRICA/INGLATERRA
			if (funcoes_gerais.StrToFloat(Latitude) >= 0) || (funcoes_gerais.StrToFloat(Longitude) >= 0) {
				continue
			}
			// FILTRA POSIÇÕES COM COORDENADAS IGUAIS OU MAIORES QUE ZERO, NO BRASIL
			//SÓ EXISTEM COORDENADAS NEGATIVAS. EVITANDO POSIÇÕES INDESEJADAS LÁ NA ÁFRICA/INGLATERRA

			//PEGA O ID DO VEÍCULO----------------------------------------------------------

			err = db.QueryRow("SELECT IDVEICULO, REGISTRAEVENTOSENTRADAS, FILTROGPS FROM VWVEICULOSCLIENTE WHERE SERIEMODULO = ?", SerieModulo).Scan(&IdVeiculo, &RegistraEventosEntradas, &FiltroGPS)
			if err == sql.ErrNoRows {
				continue
			}

			//PEGA O ID DO VEÍCULO----------------------------------------------------------

			//PEGA O ID DO MOTORISTA CASO HAJA IDENTIFICACAO--------------------------------

			if (strings.TrimSpace(ibutton) != "") && (strings.TrimSpace(ibutton) != "00000000000000") {
				err = db.QueryRow("SELECT ID AS IDMOTORISTA FROM MOTORISTAS WHERE (IDELETRONICO = ?) OR (IDELETRONICORESERVA = ?)", ibutton, ibutton).Scan(&IdMotorista)
				if err != nil {
					IdMotorista = "0"
					GeraLog(err.Error())
				}
			}

			//PEGA O ID DO MOTORISTA CASO HAJA IDENTIFICACAO--------------------------------

			//COMANDOS PARA O MÓDULO--------------------------------------------------------

			sqlcmd = "SELECT BLOQUEIOSIRENEON,DESBLOQUEIOSIRENEOFF,BLOQUEIO,DESBLOQUEIO,SIRENEON,SIRENEOFF,RESET," +
				"HORIMETRO,LIMPAMEMORIA,GETMOTORISTAS,COMANDOGENERICO FROM VWCOMANDOS WHERE SERIEMODULO = ?"
			err = db.QueryRow(sqlcmd, SerieModulo).Scan(&SetBloqueioSireneOn, &SetDesbloqueioSireneOff, &SetBloqueio, &SetDesbloqueio, &SetSireneOn, &SetSireneOff, &SetReset, &SetHorimetro, &SetLimpaMemoria, &GetMotoristas, &SetComandoGenerico)
			if err != nil {
				GeraLog(err.Error())
			} else {
				if (SetBloqueioSireneOn == "1") && (funcoes_gerais.StrToInt64(Velocidade) <= 30) {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Enable1")
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Enable2")
				}

				if SetDesbloqueioSireneOff == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Disable1")
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Disable2")
				}

				if (SetBloqueio == "1") && (funcoes_gerais.StrToInt64(Velocidade) <= 30) {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Enable1")
				}

				if SetDesbloqueio == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Disable1")
				}

				if SetSireneOn == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Enable2")
				}

				if SetSireneOff == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Disable2")
				}

				if SetReset == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;Reboot")
				}

				if SetHorimetro != "-1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;SetHMeter="+SetHorimetro)
				}

				if SetLimpaMemoria == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;EraseAll")
				}

				if GetMotoristas == "1" {
					enviaUDP(ServerConn, addr, Protocolo+"HGD;"+SerieModulo+";02;ALL")
				}

				if SetComandoGenerico != "-1" {
					enviaUDP(ServerConn, addr, Protocolo+"CMD;"+SerieModulo+";02;"+SetComandoGenerico)
				}
			}

			//COMANDOS PARA O MÓDULO--------------------------------------------------------

			//EM CASO DE ALERTA, INSERE NO REGISTRO DE ALERTAS ENVIO DO SMS E RELATÓRIO-----
			if TipoMsg == Protocolo+"ALT" {

				var EventoAlerta string
				var TipoRelatorioAlerta string

				switch funcoes_gerais.StrToInt64(AlertID) {
				case 01:
					{
						RegistraAlerta = true
						EventoAlerta = "VELOCIDADE MÁXIMA EXCEDIDA."
						TipoRelatorioAlerta = "3"
					}
				case 03:
					{
						RegistraAlerta = true
						EventoAlerta = "ANTENA GPS DESCONECTADA."
						TipoRelatorioAlerta = "4"
					}
				case 16:
					{
						RegistraAlerta = true
						EventoAlerta = "ENTROU EM COLISAO."
						TipoRelatorioAlerta = "7"
					}
				case 41:
					{
						RegistraAlerta = true
						EventoAlerta = "FALHA NA ALIMENTACAO PRINCIPAL."
						TipoRelatorioAlerta = "6"
					}
				case 45:
					{
						RegistraAlerta = true
						EventoAlerta = "BATERIA INTERNA DE BACKUP REMOVIDA."
						TipoRelatorioAlerta = "5"
					}
				case 59:
					{
						RegistraAlerta = true
						EventoAlerta = "MOTORISTA IDENTIFICADO."
						TipoRelatorioAlerta = "8"
					}
				}

				if RegistraAlerta == true {
					LocalizacaoAlerta = RetornaEndereco(Latitude, Longitude)

					sqlcmd = " INSERT INTO REGISTROSALERTAS (IDVEICULO, IDMOTORISTA, DATAHORA, EVENTO, LOCALIZACAO, TIPORELATORIO, ALERTAENVIADO, VELOCIDADE, MOVENDO) " +
						" VALUES (" + IdVeiculo + ", " + IdMotorista + ", CONVERT(DATETIME, '" + DataHoraGPS.Format("2006-01-02 15:04:05") + ".000', 121), '" + EventoAlerta + "', '" + LocalizacaoAlerta + "', " + TipoRelatorioAlerta + ", 0, '" + Velocidade + "', '" + Movendo + "') "
					stmt, err = db.Prepare(sqlcmd)
					defer stmt.Close()
					if err != nil {
						GeraLog("Registros Alertas,erro prepare: " + err.Error())
						continue
					}

					sqlres, err = stmt.Exec()
					if err != nil {
						GeraLog("Registros Alertas,erro stmt.Exec(): " + err.Error())
						continue
					}

					rowCnt, err = sqlres.RowsAffected()
					if err != nil {
						GeraLog("Registros Alertas; Erro ao tentar inserir. Registros Afetados: " + strconv.FormatInt(rowCnt, 10) + ".\r\n" + err.Error())
						continue
					}
				}
			}
			//EM CASO DE ALERTA, INSERE NO REGISTRO DE ALERTAS ENVIO DO SMS E RELATÓRIO-----

			//PEGA ULTIMA POSICAO OU REGISTRA O MODULO CASO NAO SEJA ENCONTRADO-------------

			if ModuloNaoRegistrado(SerieModulo) {
				ArrUltimaPosicao = append(ArrUltimaPosicao, TUltimaPosicao{funcoes_gerais.StrToFloat(Latitude), funcoes_gerais.StrToFloat(Longitude), SerieModulo})
			} else {
				UltimaPosicao = RetornaUltimaPosicao(SerieModulo)
				PosicaoAtual = TPonto{funcoes_gerais.StrToFloat(Latitude), funcoes_gerais.StrToFloat(Longitude)}

				if DentroPerimetroUltimaPosicao(UltimaPosicao, PosicaoAtual) || ((FiltroGPS == "1") && (Ignicao == "0")) {
					Latitude = funcoes_gerais.FloatToStr(UltimaPosicao.Lat)
					Longitude = funcoes_gerais.FloatToStr(UltimaPosicao.Lng)
				}

				AtualizaUltimaPosicao(funcoes_gerais.StrToFloat(Latitude), funcoes_gerais.StrToFloat(Longitude), SerieModulo)
			}

			//PEGA ULTIMA POSICAO OU REGISTRA O MODULO CASO NAO SEJA ENCONTRADO-------------

			var Modelo string

			if Protocolo == "SA200" {
				Modelo = "STT2XX"
			}
			if Protocolo == "ST300" {
				Modelo = "STT3XX"
			}

			//INSERE NA TABELA DE ATUALZACOES-----------------------------------------------

			sqlcmd = " INSERT INTO ATUALIZACOES (STATUSPOSICAO, TIPOMSG, STATUSGPS, DATAHORA, DATAHORAGPS, LONGITUDE, LATITUDE, VELOCIDADE, IDMODULO, IGNICAO, ANTIFURTO, SAIDAS1, SAIDAS2, PANICO, ENTRADAS1, ENTRADAS2, ENTRADAS3, ENTRADAS4, SAIDAS3, SAIDAS4, DIRECAO, VELOCIDADEMAXIMAEXCEDIDA, BATERIACARREGANDO, FALHABATERIAINTERNA, FALHAALIMENTACAOPRINCIPAL, MOVENDO, TENSAO, HODOMETRO, HORIMETRO, RPM, INDICEPOSICAOMXT, MODELO, IDMOTORISTA) VALUES ('" + StatusPosicao + "', '4', '" + GPSValido + "', CONVERT(DATETIME, '" + DataHora.Format("2006-01-02 15:04:05") + ".000', 121), CONVERT(DATETIME, '" + DataHoraGPS.Format("2006-01-02 15:04:05") + ".000', 121), '" + Longitude + "', '" + Latitude + "', '" + Velocidade + "', " + IdModulo + ", '" + Ignicao + "', '" + Antifurto + "', '" + Saida1 + "', '" + Saida2 + "', '" + Panico + "', '" + Entrada1 + "', '" + Entrada2 + "', '" + Entrada3 + "', '" + Entrada4 + "', '" + Saida3 + "', '" + Saida4 + "', '" + Direcao + "', '" + VelocidadeMaximaExcedida + "', '" + BateriaCarregando + "', '" + FalhaBateriaInterna + "', '" + FalhaAlimentacaoPrincipal + "', '" + Movendo + "', '" + Tensao + "', " + Hodometro + ", " + Horimetro + ", " + Rpm + ", '0', '" + Modelo + "', " + IdMotorista + ") "
			stmt, err = db.Prepare(sqlcmd)
			defer stmt.Close()
			if err != nil {
				GeraLog("Insert Atualizacoes; erro prepare: " + err.Error())
				continue
			}

			sqlres, err = stmt.Exec()

			if err != nil {
				GeraLog("Insert Atualizacoes; erro stmt.Exec(): " + err.Error())
				GeraLog(sqlcmd)
				continue
			}

			rowCnt, err = sqlres.RowsAffected()
			if err != nil {
				GeraLog("Erro ao tentar inserir. Registros Afetados: " + strconv.FormatInt(rowCnt, 10) + ".\r\n" + err.Error())
			}

			//INSERE NA TABELA DE ATUALZACOES-----------------------------------------------

		} //FIM if (TipoMsg == Protocolo+"STT") || (TipoMsg == Protocolo+"ALT") {........

		if (TipoMsg == Protocolo+"CMD") || ((TipoMsg == Protocolo+"HGD") && (Dados[1] == "Res")) { //ACK vinda do rastreador
			//RECEBEU CONFIRMAÇÃO DO MÓDULO, ENTÃO RESETA TODOS OS COMANDOS SETANDO "0" E SETA RESPOSTA = "1"-----

			sqlcmd = " UPDATE COMANDOS SET COMANDOGENERICO='-1', GETMOTORISTAS=0, BLOQUEIO=0, BLOQUEIOPROGRESSIVO=0, BLOQUEIOSIRENEON=0, DESBLOQUEIO=0, DESBLOQUEIOSIRENEOFF=0, SIRENEON=0, SIRENEOFF=0, NUM1=0, NUM2=0, NUM3=0, NUM4=0, LEDRED=0, LEDGREEN=0, LEDX=0, " +
				" RESPOSTA=1, INTERVALO=0, PANICO=0, RESET=0, DESATIVAFILTROGPS=0, ATIVAFILTROGPS=0, POWEROFF=0, LIMPAMEMORIA=0, HORIMETRO='-1', CONFIGIP='-1' " +
				" WHERE IDMODULO = (SELECT ID FROM MODULOS WHERE SERIEMODULO = ?) "
			stmt, err = db.Prepare(sqlcmd)
			defer stmt.Close()
			if err != nil {
				GeraLog("Update reset comandos; erro prepare: " + err.Error())
				continue
			}

			sqlres, err = stmt.Exec(SerieModulo)

			if err != nil {
				GeraLog("Update reset comandos; erro stmt.Exec(): " + err.Error())
				GeraLog(sqlcmd)
				continue
			}

			rowCnt, err = sqlres.RowsAffected()
			if err != nil {
				GeraLog("Erro ao tentar efeturar o UPDATE na tabela comandos. Registros Afetados: " + strconv.FormatInt(rowCnt, 10) + ".\r\n" + err.Error())
			}

			//RECEBEU CONFIRMAÇÃO DO MÓDULO, ENTÃO RESETA TODOS OS COMANDOS SETANDO "0" E SETA RESPOSTA = "1"-----
		}

		//debug.FreeOSMemory() //GARBAGE COLLECT
	} //FIM LOOP SERVICO UDP..........................
}

The deferred methods in the infinite for loop will never run as the function never exits.

1 Like

I see line 520: stmt, err := db.Prepare(sqlcmd). But nowhere are you calling Close() on stmt. You must call Close() according to the documentation of DB.Prepare().

On lines 572 and 602 you call defer stmt.Close(). Deferred statements are only run when the function it was called in returns. Because main never returns the deferred statements are never executed! I believe this is the root cause of your runaway memory issues.

I also see a potential SQL injection attack on line 570 sqlcmdatualizacao := " INSERT INTO ATUALIZACOES.... Perhaps use a prepared statement here as well.

You have many “helper” functions that just hide a tiny bit of boilerplate. Most of them are unnecessary and make the code more difficult to read. Remove them.

At the same time the enormous main() function desperately needs refactoring into smaller pieces. This is very different from what you’ve done with the “helper” functions. Put each labeled section into a new function that takes parameters and returns a result (don’t use globals!, pass only the values that section needs to execute).

Here’s a list of changes I would make to this code:

  • Instead of defining a large number of variables at the top of the loop, define a couple structs and use them to pass data between main and these new functions.
  • Separate the position/alert handler into its own function.
  • Separate the confirmation handler into its own function.
  • Put each of the protocol handlers into their own functions. (lines 137, 234)
  • Lines 347-370 should be a function AngleToDirection(angle int) string. This is different from your “helper” functions because it makes decisions, it doesn’t just hide boilerplate.

Just these refactorings will fix the memory issues you’re encountering due to defers never running. It will also be easier to debug future problems.

1 Like

I did all my friends told me on here,and it still increases memory usage… I really dunno nothing else to do in order to solve that problem… Too bad…

you can try to identify the sequence that consume memory with runtime package by inserting and logging snippets like in the following example, after your queries in the loop

package main

import (
	"log"
	"runtime"
)

func main() {
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	log.Println(m.Alloc)
	s := make([]byte, 1024*1024)
	s[0] = 0
	runtime.ReadMemStats(&m)
	log.Println(m.Alloc)
}

also,see here a more detailed example.

in this way i guess you should see after some iterations what sequence increase the memory more than is expected…

1 Like

This is th perfect use case for th execution tracer. Trace your program then you’ll be able to see the increase in heap and to trace it to the code running at the time.

1 Like