더북(TheBook)

display() 함수

display() 함수는 필터링된 최종 결과를 in 채널로 전달받아 화면에 출력한다.

import "fmt"
 
func display(in <-chan string) <-chan struct{} {
    quit := make(chan struct{})
    go func() {
        for file := range in {
            c, err := lineCount(file)
            if err != nil {
                fmt.Println(err)
                continue
            }
            fmt.Printf("%8d %s\n", c, file)
        }
        quit <- struct{}{}
    }()
    return quit
}

find(), grep() 함수와 마찬가지로 실제 작업은 고루틴으로 동작한다. in 채널에 필터링 결과가 전달되면 라인 수를 계산해서 화면에 출력하고, 모든 작업이 완료되면 quit 채널로 신호를 보낸다. main 함수에서는 quit 채널로 전체 작업의 완료 상황을 인지한다.

lineCount() 함수는 다음과 같이 작성한다.

import (
    "bytes"
    "io"
    "os"
)
 
func lineCount(file string) (int, error) {
    f, err := os.Open(file)
    if err != nil {
        return 0, err
    }
    defer f.Close()
     
    info, err := f.Stat()
    if err != nil {
        return 0, err
    }
    if info.Mode().IsDir() {
        return 0, fmt.Errorf("%s is a directory", file)
    }
     
    count := 0
    buf := make([]byte, 1024*8)
    newLine := []byte{'\n'}
    
    for {
        c, err := f.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }
       
        count += bytes.Count(buf[:c], newLine)
    
        if err == io.EOF {
            break
        }
    }
    return count, nil
}

파일에 있는 줄 바꿈 문자(\n)를 세서 전체 라인 수를 계산했다. bytes, io, os 패키지는 7장에서 상세히 다룬다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.