func FindWordInAllFiles(word, path string) []FindInfo {
findInfos := []FindInfo{}
- filelist, err := GetFileList(path)
+ filelist, err := filepath.Glob(path)
....
+ ch := make(chan FindInfo)
+ cnt := len(filelist)
+ recvCnt := 0
for _, filename := range filelist {
- findInfos = append(findInfos, FindWordInFiles(word, filename))
+ go FindWordInFile(word, filename, ch)
}
+ for findInfo := range ch {
+ findInfos = append(findInfos, findInfo)
+ recvCnt++
+ if recvCnt == cnt {
+ break
+ }
+ }
+ return findInfos
+}
- func FindWordInFiles(word, filename string) FindInfo {
+ func FindWordInFile(word, filename string, ch chan FindInfo) {
findInfo := FindInfo{filename, []LineInfo{}}
file, err := os.Open(filename)
...
- return findInfo
+ ch <- findInfo
}
찾아볼 것, 궁금한 것 목록
대충 쥐뿔도 모르는 상태에서 어떻게 돌아가는지 생각해보기.
- chan FindInfo 라는 놈을 만듬(make)
- filelist 에 들어있는 파일 개수 만큼 FindWordInFile 함수로 가서(go) 실행하라고 명령
- FindWordInFile 이 어쩌구 저쩌구 실행된 끝에 원하는 결괏값을 ch 에 넣어줌
- 넣어진 결괏값을 끄집어내서 findInfos 에 병합
-
GetFileList(path) 를 filepath.Glob(path) 로 대체. 근데 GetFileList(path) 구현은 정확히 filepath.Glob(path) 한 줄이라서 동일함. 오타 같기도
-
ch chan FindInfo 에서 chan FindInfo 는 하나의 키워드처럼 쓰임 (구조체마다 다르겠지만, 쨋든 한 덩어리). 그냥 chan 으로 받을 수 없나? C에서 void 같은 역할을 하는놈은 없나?
- 현재까지 찾아본 바로는 못 찾았음
- ch <- findInfo 라고 적으면 느낌적으로 대입하는거 같은데, 또 호출된 곳으로 돌아가보면 range ch 를 하고 있음. 배열같기도 하고... chan 의 개념을 잠깐 들여다볼 필요가 있을듯
- 고루틴(goroutine)은 가벼운 쓰레드쯤 되는듯. 채널은 고루틴들을 연결해주는 파이프쯤 되는듯. main 고루틴 에서 도는 FindWordInAllFiles 함수와 go 키워드로 만든 별도의 FindWordInFiles 함수에 대한 고루틴들 사이를 연결하는 용도로 채널을 도입
- v, ok := <- ch 해도 값을 얻을 수 있음 for { v, ok := <- ch if ok == false { ... }
대충 이딴식으로도 만들 수 있을듯. 다만 range 를 쓰면, 어떤일이 일어나는지 보자. receives values from the channel repeatedly until it is closed. (https://tour.golang.org/concurrency/4)
채널이 닫히기 전까지 계속 반복적으로 값을 끄집어낸다고 한다. 그렇다면 값이 없는데 채널은 열려있다면? 대기타나???
- 한 가지 흥미로운 사실은 채널이 역할을 다 했을때 반드시 닫아(close) 해줄 필요는 없다는것. 더 이상 값이 없음을 반드시 통지해야만 한다면, 그 때는 close 로 채널을 닫아준다. 그 외에는 돈케어
- for findInfo := range ch 라고 범위 동안 반복해라 해놓고, if recvCnt == cnt 로 탈출시킴. 그냥 for { ... if recvCnt == cnt { ... } ... } 해도 되는것 아님? 왜 range ch 가 필요한가? 이 방식으로만 ch 에 담긴 findInfo 를 끄집어내야하나?
- 대충 보아하니 range 를 쓰는 이유는, 채널은 일종의 큐 같이 값 목록을 가질 수 있는 구조인듯. 그리고 range 를 통한 이터레이션은 큐에 값이 존재할 때만 발동하는듯.
- 큐니 뭐니 하기때문에, 사이즈 지정도 가능함 예. queue := make(chan string, 2)