더북(TheBook)

맵 단계

각 토큰의 위치 정보를 나타내는 partial 타입을 다음과 같이 정의한다.

import "text/scanner"
 
type partial struct {
    token string
    scanner.Position
}

text/scanner 패키지가 제공하는 타입인 scanner.Position은 토큰의 위치 정보를 담고 있다.

Note scanner.Position 타입

// http://golang.org/pkg/text/scanner/#Position
type Position struct {
    Filename string // 파일명
    Offset   int    // 오프셋(byte 단위, 0부터 시작)
    Line     int    // 줄 번호(1부터 시작)
    Column   int    // 칼럼 번호(1부터 시작)
}

mapper() 함수는 각 파일의 토큰과 토큰의 위치 정보를 추출하여 out 채널로 전달한다.

func mapper(path string, out chan<- partial) {
    file, err := os.Open(path)
    if err != nil {
        return
    }
    defer file.Close()
     
    // 정상적인 파일이 아닌 경우 바로 반환
    if info, err := file.Stat(); err != nil || info.Mode().IsDir() {
        return
    }
     
    var s scanner.Scanner
    s.Filename = path
    s.Init(file)
     
    // 파일의 모든 토큰을 스캔하여 out 채널로 전송
    tok := s.Scan()
    for tok != scanner.EOF {
        fmt.Println(s.Pos())
        out <- partial{s.TokenText(), s.Pos()}
        tok = s.Scan()
    }
}

다음은 매퍼(mapper)를 실행하는 함수이다.

func runMap(paths <-chan string) <-chan partial {
    out := make(chan partial, BUF_SIZE)
    go func() {
        for path := range paths {
            mapper(path, out)
        }
        close(out)
    }()
    return out
}

파일 목록은 paths 채널을 통해 runMap() 함수 내부로 전달된다. 각 pathmapper()를 실행하는 작업은 고루틴으로 동작한다. 이때 CPU의 코어 수만큼 여러 개의 고루틴을 만들어 동시에 동작하게 했다. mapper() 함수로 추출된 토큰 정보는 out 채널을 통해 외부로 전달된다.

전체 코드는 map.go를 참고하기 바란다.

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