2017-09-07 2 views
0

Je souhaite écrire une fonction qui lit les lignes d'un fichier et les envoie ensuite dans un canal pour un traitement ultérieur. Je suis nouveau aller et est ici la fonction de lecteur, je suis venu avec après la plupart des exemples de manuels:Comment numériser un fichier ligne par ligne dans une fonction anonyme et le transmettre à un canal

func reader(file string) <-chan string { 
    out := make(chan string) 

    f, err := os.Open(file) 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer f.Close() 

    s := bufio.NewScanner(f) 
    go func() { 
     for s.Scan() { 
      out <- s.Text() 
     } 
     close(out) 
    }() 

    return out 
} 

Dans la fonction main() je passe un pointeur de fichier dans la fonction de lecture et d'essayer de drainer le canal comme suit :

func main() { 
    out := reader(*f) 
    for range out { 
     fmt.Println(<-out) 
    } 
} 

Je reçois aucune erreur de comilation ou exécution, cependant, la sortie est vide. Si je ne mets pas la boucle for dans un goroutine, je peux imprimer le fichier à partir de la fonction reader() sans aucun problème.

J'ai également essayé de passer le scanner, le canal ou les deux dans la fonction reader() dans la fonction anonyme. Mais cela n'a pas résolu le problème. Quelqu'un peut-il expliquer s'il vous plaît pourquoi ce code ne fonctionne pas et comment y remédier?

Répondre

0

Vous fermez le fichier avant de le lire.

Vous imprimez uniquement une ligne sur deux.

Déplacez le report dans la fermeture où les lectures se produisent réellement.

func reader(file string) <-chan string { 
    out := make(chan string) 

    f, err := os.Open(file) 
    if err != nil { 
     log.Fatal(err) 
    } 

    s := bufio.NewScanner(f) 
    go func() { 
     defer f.Close() 
     defer close(out) 
     for s.Scan() { 
      out <- s.Text() 
     } 
     if err := s.Err(); err != nil { 
      fmt.Println("error reading file:", err) 
     } 
    }() 

    return out 
} 

imprimer Ensuite, la valeur de la clause de plage, pas une seconde valeur reçue dans la boucle:

func main() { 
    out := reader(os.Args[1]) 
    for line := range out { 
     fmt.Println(line) 
    } 
}