Cuidado com o escopo de suas variáveis: gh-cleaner e seu bug inesperado
Motivação
Para quem viu meu Post anterior sabe que estou trabalhando com um projeto de deletador de repositórios github com inteligencia artificial, mais especificamente o classificador chamado naive bayes.
Este é um exercicio de programação citado pelo Akita em Entendendo o Dilema das Redes.
E para fazer isso, se você estiver acompanhando meu repositório no github pode ver que eu estava separando em um local escondido algumas pastas chamada "bayes_theorem/savedRepo" e "bayes_theorem/deletedRepo" contendo um json com todas as estruturas de github.Repository.
Esse é um fato importante já que eu quero descobrir qual seria o principal caracter de um repositório que me fez deleta - lo e sortear a lista de repositórios para probabilisticamente descobrir qual é o repositório que eu tenho a maior chance de deletar conforme os anteriores.
O infrator
Mas no momento em que escrevi essa função chamada ReadJson, eu vi um comportamento estranho, o repositório que deveria ser deletedRepo apareceu savedRepo. E eu cacei, fucei e tudo mais para encontrar o problema.
package fileutils
import (
"encoding/json"
"fmt"
"os"
"strings"
"github.com/google/go-github/v61/github"
)
var Repos []*github.Repository
func ReadJson(path string) []*github.Repository {
exists := FileExists(path)
if exists {
arquivos, err := os.ReadDir(path)
if err != nil {
fmt.Printf("Error in opening the read dir %s: %v\n", path, err)
return nil
}
for _, arquivo := range arquivos {
var repo *github.Repository
if !arquivo.IsDir() && strings.HasSuffix(arquivo.Name(), ".json") {
data, err := os.ReadFile(path + "/" + arquivo.Name())
if err != nil {
fmt.Printf("Error in read the file %s: %v\n", path, err)
return nil
}
err = json.Unmarshal(data, &repo)
if err != nil {
fmt.Printf("Error in unmarshaling the json: %v", err)
return nil
}
Repos = append(Repos, repo)
}
}
return Repos
}
fmt.Printf("Error path %s not founded\n", path)
return nil
}
Poizé, o problema está justamente na variável global Repos que eu havia criado.
Isso aconteceu por eu chamo duas vezes a ReadJson no meu projeto, uma para pegar os savedRepo e outra para pegar os deletedRepo e contendo uma variável global a memória não é limpa ao encerrar a função, fazendo com que esse comportamento inesperado a aparecesse.
A solução
Então para resolver isso a solução mais obvia foi mover a variavel global para uma variavel local e devolver uma copia do valor
func ReadJson(path string) []github.Repository {
var Repos []github.Repository
exists := FileExists(path)
if exists {
arquivos, err := os.ReadDir(path)
if err != nil {
fmt.Printf("Error in opening the read dir %s: %v\n", path, err)
return nil
}
for _, arquivo := range arquivos {
var repo github.Repository
if !arquivo.IsDir() && strings.HasSuffix(arquivo.Name(), ".json") {
data, err := os.ReadFile(path + "/" + arquivo.Name())
if err != nil {
fmt.Printf("Error in read the file %s: %v\n", path, err)
return nil
}
err = json.Unmarshal(data, &repo)
if err != nil {
fmt.Printf("Error in unmarshaling the json: %v", err)
return nil
}
Repos = append(Repos, repo)
}
}
return Repos
}
Isso foi o suficiente para eu conseguir corrigir minha função. E quero deixar o adendo que esse tipo de erro pode ocorrer muito facilmente se você não prestar atenção no escopo das variaveis do seu código principalmente ao trabalhar com copia / referencia ou ponteiros já que na pressa você pode não ver a bomba chegando no colo.
Felizmente consegui encontrar a batata quente a tempo. Espero que essa dica possa ajudar nos seus projetos.