최근에 보니 흥미로 웠습니다. 튜토리얼을 마친 후에는 혼자서 무언가를 만들고 싶었습니다. 음악 라이브러리의 모든 노래를 나열하고 싶습니다. 나는 여기서 go의 동시성으로부터 이익을 얻을 수 있다고 생각한다. 루틴에서 디렉토리 트리를 따라 가면서 음악 파일 (해당 파일의 경로)을 채널로 밀어 넣은 다음 ID3 태그를 읽는 다른 루틴에 의해 선택되므로 모든 파일을 찾을 때까지 기다릴 필요가 없습니다. .골란의 교착 상태 오류
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
"sync"
)
const searchPath = "/Users/luma/Music/test" // 5GB of music.
func main() {
files := make(chan string)
var wg sync.WaitGroup
wg.Add(2)
go printHashes(files, &wg)
go searchFiles(searchPath, files, &wg)
wg.Wait()
}
func searchFiles(searchPath string, files chan<- string, wg *sync.WaitGroup) {
visit := func(path string, f os.FileInfo, err error) error {
if !f.IsDir() && strings.Contains(".mp4.mp3.flac", filepath.Ext(f.Name())) {
files <- path
}
return err
}
if err := filepath.Walk(searchPath, visit); err != nil {
fmt.Println(err)
}
wg.Done()
}
func printHashes(files <-chan string, wg *sync.WaitGroup) {
for range files {
fmt.Println(<-files)
}
wg.Done()
}
이 프로그램은 아직 태그를 읽지 않습니다 :
이 내 단순하고 순진 방법입니다. 대신 단지 파일 경로를 출력합니다. 이 기능은 모든 음악 파일을 매우 빠르게 나열합니다! 그러나 프로그램이 끝난 후에이 오류가 나타납니다.
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc42007205c)
/usr/local/Cellar/go/1.7.4_2/libexec/src/runtime/sema.go:47 +0x30
sync.(*WaitGroup).Wait(0xc420072050)
/usr/local/Cellar/go/1.7.4_2/libexec/src/sync/waitgroup.go:131 +0x97
main.main()
/Users/luma/Code/Go/src/github.com/LuMa/test/main.go:22 +0xfa
goroutine 17 [chan receive]:
main.printHashes(0xc42008e000, 0xc420072050)
/Users/luma/Code/Go/src/github.com/LuMa/test/main.go:42 +0xb4
created by main.main
/Users/luma/Code/Go/src/github.com/LuMa/test/main.go:19 +0xab
exit status 2
교착 상태의 원인은 무엇입니까?
항상 WaitGroup.Done()을 연기하십시오. 완료라고하지 않는 첫 번째 goroutine의 반환 경로가 있습니다. – JimB
@JimB 거의 저도 있어요. 그러나 리턴 경로가 아니라는 것을 알아 두십시오. 인라인 함수는 선언되어 다른 함수로 전달됩니다.이 함수는 하나의 실행 경로 만 가지고 있습니다. 하지만 네, 전형적인 관행은'defer wg.Done() '을 호출해야합니다. – eduncan911
@ eduncan911 : 감사합니다. 조기 반환을 스캔하고 충분히 자세히 읽지 않았습니다. – JimB