godirwalk 는 파일 시스템에서 디렉토리 트리를 가로 지르는 라이브러리입니다.
요컨대, 왜이 라이브러리를 만들었습니까?
filepath.Walk 보다 빠릅니다.filepath.Walk 보다 더 정확합니다.filepath.Walk 보다 사용하기가 더 쉽습니다.filepath.Walk 보다 유연합니다.특정 상황에 따라 더 이상 파일을 걷기 위해 라이브러리가 필요하지 않을 수 있습니다.
추가 예제는 examples/ 서브 디렉토리에 제공됩니다.
이 라이브러리는 첫 번째 인수에서 filepath.Clean 호출하여 OS- 특이 경로 분리기를 기반으로 제공된 최상위 디렉토리 이름을 정규화합니다. 그러나 제공된 콜백 함수를 호출 할 때 올바른 OS- 특이 경로 분리기를 사용하여 생성 된 PathName을 항상 제공합니다.
dirname := "some/directory/root"
err := godirwalk . Walk ( dirname , & godirwalk. Options {
Callback : func ( osPathname string , de * godirwalk. Dirent ) error {
// Following string operation is not most performant way
// of doing this, but common enough to warrant a simple
// example here:
if strings . Contains ( osPathname , ".git" ) {
return godirwalk . SkipThis
}
fmt . Printf ( "%s %s n " , de . ModeType (), osPathname )
return nil
},
Unsorted : true , // (optional) set true for faster yet non-deterministic enumeration (see godoc)
}) 이 라이브러리는 파일 시스템 디렉토리 트리를 가로 지르는 기능을 제공 할뿐만 아니라 특정 디렉토리의 즉각적인 후손 목록을 얻기위한 기능 os.ReadDirnames 제공합니다 os.ReadDir
다음은 filepath.Walk , os.ReadDir 및 os.ReadDirnames 보다 godirwalk 선호하는 이유입니다.
filepath.Walk 보다 빠릅니다 벤치 filepath.Walk 에서 Walk와 비교할 때, UNIX find 유틸리티의 속도와 비교할 수있는 속도로 Darwin의 속도의 5 배에서 10 배 사이에 실행되는 것으로 관찰되었습니다. 그리고 Linux의 속도의 약 2 배; 그리고 창에서 속도의 약 4 배.
이 성능 향상을 어떻게 얻습니까? 거의 동일한 출력을 제공하는 작업이 적습니다. 이 라이브러리는 동일한 syscall 기능을 호출하여 작업을 수행하지만, 호출이 적고, 필요한 정보를 버리지 않으며, 운영 체제에서 파일 시스템 입력 데이터를 읽을 때마다 새 버퍼를 재 할 수있는 대신 디렉토리에서 읽기 위해 동일한 스크래치 버퍼를 재사용하여 그 길을 따라 메모리 휘발을 덜 만듭니다.
파일 시스템 디렉토리 트리를 통과하는 동안 filepath.Walk 디렉토리의 즉각적인 자손 목록을 얻고 노드 이름과 함께 제공되는 운영 체제에서 제공하는 파일 시스템 항목의 노드 유형 정보를 버립니다. 그런 다음 콜백 함수를 호출하기 직전에 filepath.Walk 각 노드의 os.Stat 호출하고 반환 된 os.FileInfo 정보를 콜백으로 전달합니다.
os.Stat 에서 제공하는 os.FileInfo 정보는 매우 유용하지만 os.FileMode 데이터가 포함되어 있지만 각 노드에 대한 추가 시스템 호출이 필요합니다.
대부분의 콜백은 노드 유형의 내용에만 관심이 있기 때문에이 라이브러리는 유형 정보를 버리지 않고 os.FileMode 값의 형태로 해당 정보를 콜백 기능에 제공합니다. 이 라이브러리가 제공하는 제공된 os.FileMode 값에는 노드 유형 정보 만 가지고 있으며 파일 모드의 권한 비트, 스티커 비트 또는 기타 정보가 없습니다. 콜백이 특정 노드의 전체 os.FileInfo 데이터 구조에 관심이있는 경우, 콜백은 필요할 때만 os.Stat ESIIY로 호출 할 수 있습니다.
$ go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: github.com/karrick/godirwalk
BenchmarkReadDirnamesStandardLibrary-12 50000 26250 ns/op 10360 B/op 16 allocs/op
BenchmarkReadDirnamesThisLibrary-12 50000 24372 ns/op 5064 B/op 20 allocs/op
BenchmarkFilepathWalk-12 1 1099524875 ns/op 228415912 B/op 416952 allocs/op
BenchmarkGodirwalk-12 2 526754589 ns/op 103110464 B/op 451442 allocs/op
BenchmarkGodirwalkUnsorted-12 3 509219296 ns/op 100751400 B/op 378800 allocs/op
BenchmarkFlameGraphFilepathWalk-12 1 7478618820 ns/op 2284138176 B/op 4169453 allocs/op
BenchmarkFlameGraphGodirwalk-12 1 4977264058 ns/op 1031105328 B/op 4514423 allocs/op
PASS
ok github.com/karrick/godirwalk 21.219s$ go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: github.com/karrick/godirwalk
BenchmarkReadDirnamesStandardLibrary-12 100000 15458 ns/op 10360 B/op 16 allocs/op
BenchmarkReadDirnamesThisLibrary-12 100000 14646 ns/op 5064 B/op 20 allocs/op
BenchmarkFilepathWalk-12 2 631034745 ns/op 228210216 B/op 416939 allocs/op
BenchmarkGodirwalk-12 3 358714883 ns/op 102988664 B/op 451437 allocs/op
BenchmarkGodirwalkUnsorted-12 3 355363915 ns/op 100629234 B/op 378796 allocs/op
BenchmarkFlameGraphFilepathWalk-12 1 6086913991 ns/op 2282104720 B/op 4169417 allocs/op
BenchmarkFlameGraphGodirwalk-12 1 3456398824 ns/op 1029886400 B/op 4514373 allocs/op
PASS
ok github.com/karrick/godirwalk 19.179sfilepath.Walk 보다 더 정확합니다나는 이전에 이것에 대해 신경 쓰지 않았지만 유머. 우리 모두는 한 번 글을 쓰고 어디서나 달릴 수있는 방법을 좋아합니다. 언어 채택, 성장 및 성공에 필수적이며, 우리가 만든 소프트웨어는 GO가 지원하는 모든 아키텍처 및 운영 체제에서 수정되지 않은 실행할 수 있습니다.
트래버스 파일 시스템에 디렉토리에 대한 상징적 링크로 인한 논리적 루프가있는 경우 Unix filepath.Walk 상징적 링크를 무시하고 오류없이 전체 디렉토리 트리를 가로 지릅니다. 그러나 Windows에서는 filepath.Walk 디렉토리를 계속해서 기호 링크를 계속 진행할 것입니다. 그러나 결국 filepath.Walk 조기에 종료되고 PathName이 PathName에 대한 끝없는 고리를 연결하는 데 너무 길어질 때 FilePath.Walk가 일찍 종료되고 오류를 반환 할 수 있습니다. 이 오류는 Windows에서 나오고 filepath.Walk 및 업스트림 클라이언트를 실행하는 filepath.Walk 로 전달됩니다.
테이크 아웃은 행동이 어떤 플랫폼 filepath.Walk 가 실행 중인지에 따라 행동이 다르다는 것입니다. 이것은 분명히 의도적이지 않지만 표준 라이브러리에 고정 될 때까지 호환성 문제를 나타냅니다.
이 라이브러리는 위의 문제를 해결하여 UNIX 또는 Windows의 논리 파일 SYTEM 루프를 따르지 않도록합니다. 더욱이, FollowSymbolicLinks true로 설정된 경우에만 상징적 링크를 따릅니다. Windows 및 기타 운영 체제의 동작은 동일합니다.
filepath.Walk 보다 사용하기가 더 쉽습니다 이 라이브러리는 엄청나게 잘 쓰여진 filepath.Walk 의 동작을 모방하기 위해 노력하지만, 워크 표준 라이브러리는 더 쉽고 직관적 인 발신자 인터페이스를 제공하기 위해 약간 벗어난 곳이 있습니다.
이 라이브러리는 모든 파일 시스템 노드에서 os.Stat 를 호출하지 않으므로 콜백 기능이 필터링 할 수있는 오류 이벤트가 없습니다. os.Stat 에서 콜백 함수로 오류를 전달하는 filepath.WalkFunc 함수 서명의 세 번째 인수는 더 이상 필요하지 않으므로이 라이브러리에서 콜백 함수의 서명에서 제거됩니다.
또한 filepath.WalkFunc 과이 라이브러리의 WalkFunc 간의이 약간의 인터페이스 차이는 filepath.Walk 사용할 때 콜백 처리기가 작성 해야하는 보일러 플레이트 코드를 제거합니다. 전달 된 오류 값을 확인 해야하는 모든 콜백 함수와 그에 따라 분기에 오류 값을 확인하는 대신이 라이브러리의 사용자는 콜백 함수에 입력하면 즉시 확인할 오류 값조차 없습니다. 이것은 런타임 성능과 코드 선명도 모두에서 개선 된 것입니다.
모든 OS 플랫폼에서 filepath.Walk solidus ( / ) 구분 된 PathName으로 콜백 함수를 호출합니다. 대조적 으로이 라이브러리는 OS- 특이 적 PathName 분리기를 사용하여 콜백을 호출하여 제공된 PathName을 실제로 사용하기 전에 각 노드의 콜백 함수에서 filepath.Clean 에 대한 호출을 제거합니다.
다시 말해, Windows에서도 filepath.Walk some/path/to/foo.txt 로 콜백을 호출하여 지정된 파일로 작업하기 전에 모든 파일에 대해 PathName 정규화를 수행해야합니다. 이것은 진정한 OS 비율 콜백 함수를 만들기위한 숨겨진 보일러 플레이트 요구 사항입니다. 사실, 많은 고객이 유닉스에서 개발되었고 Windows에서 테스트되지 않은이 미묘함을 무시하고 누군가가 Windows에서 해당 소프트웨어를 실행하려고 할 때 소프트웨어 버그를 초래할 것입니다.
이 라이브러리는 Windows에서 실행할 때 동일한 파일에 대해 somepathtofoo.txt 로 콜백 함수를 호출하여 클라이언트의 경로 이름을 정규화 할 필요가 없으며 클라이언트가 Windows에서 작동하지 않을 가능성을 줄입니다.
이 향상은 콜백 기능에서 더 많은 보일러 플레이트 코드의 필요성을 제거 하면서이 라이브러리의 런타임 성능을 향상시킵니다.
godirwalk.SkipThis filepath.SkipDir 보다 사용하기에 더 직관적입니다 이 라이브러리가 모방 해야하는 filepath.WalkFunc 인터페이스의 혼란스러운 측면 중 하나는 발신자가 파일 시스템 항목을 건너 뛰기 위해 Walk 기능을 알려주는 방법입니다. 콜백 함수가 디렉토리를 건너 뛰고 어린이로 내려 가지 않고 디렉토리를 건너 뛰고 싶을 때 filepath.Walk 와이 라이브러리의 Walk 모두 사용하면 filepath.SkipDir 반환합니다. 콜백 함수가 비 디렉토리에 대해 filepath.SkipDir 반환하면 filepath.Walk 와이 라이브러리는 현재 디렉토리에서 더 이상 항목 처리를 중지합니다. 이것이 반드시 대부분의 개발자가 원하거나 기대하는 것은 아닙니다. 특정 비 디렉토리 항목을 건너 뛰고 디렉토리에서 처리 항목을 계속 건너 뛰려면 콜백 함수가 NIL을 반환해야합니다.
이 인터페이스 설계의 의미는 파일 시스템 계층을 걸어 가고 항목을 건너 뛰려면 노드가 어떤 파일 시스템 입력 유형에 따라 다른 값을 반환해야합니다. 항목을 건너 뛰려면 항목이 디렉토리 인 경우 filepath.SkipDir 반환해야하며 항목이 디렉토리가 아닌 경우 nil 반환해야합니다. 이것은 내가 직관적 인 인터페이스가 아니기 때문에 많은 개발자들이 고군분투하는 것을 관찰 한 불행한 장애물입니다.
다음은 filepath.WalkFunc 인터페이스를 준수하는 예제 콜백 함수입니다. 전체 PathName에 특정 부분 문자열이 포함 된 파일 시스템 항목을 건너 뛰 optSkip 하십시오. 이 라이브러리는 여전히 콜백 함수가 filepath.SkipDir 반환 할 때 filepath.Walk 의 동일한 동작을 지원합니다.
func callback1 ( osPathname string , de * godirwalk. Dirent ) error {
if optSkip != "" && strings . Contains ( osPathname , optSkip ) {
if b , err := de . IsDirOrSymlinkToDir (); b == true && err == nil {
return filepath . SkipDir
}
return nil
}
// Process file like normal...
return nil
} 이 라이브러리는 새로운 토큰 오류 값 인 SkipThis 제공하여 콜백 함수에 필요한 논리 보일러 플레이트 중 일부를 제거하려고 시도합니다. 현재 항목이 디렉토리 인 경우, 콜백이 filepath.SkipDir 반환 한 것처럼 어린이가 열거되지 않습니다. 현재 항목이 비 디렉토리 인 경우, 콜백이 nil 반환 한 것처럼 현재 디렉토리의 다음 파일 시스템 항목이 열거됩니다. 다음 예제 콜백 함수는 이전과 동일한 동작을 가지고 있지만 보일러 플레이트는 적으며, 더 간단하게 찾는 논리를 가지고 있습니다.
func callback2 ( osPathname string , de * godirwalk. Dirent ) error {
if optSkip != "" && strings . Contains ( osPathname , optSkip ) {
return godirwalk . SkipThis
}
// Process file like normal...
return nil
}filepath.Walk 보다 유연합니다 이 라이브러리의 기본 동작은 filepath.Walk 와 마찬가지로 디렉토리 트리를 걸을 때 디렉토리에 대한 상징적 링크를 무시하는 것입니다. 그러나 상징적 링크를 포함하여 찾은 각 노드와 함께 콜백 기능을 호출합니다. 디렉토리 트리를 통과 할 때 기호 링크를 따르는 특정 사용 사례가 존재하는 경우,이 라이브러리는 FollowSymbolicLinks config 매개 변수를 true 로 설정하여 그렇게 할 수 있습니다.
이 라이브러리의 기본 동작은 filepath.Walk 와 마찬가지로 각 노드를 방문하기 전에 항상 디렉토리의 즉각적인 후손을 정렬하는 것입니다. 이것은 일반적으로 원하는 행동입니다. 그러나 디렉토리 노드에 많은 항목이있을 때 이름을 정렬하는 데 필요한 약간의 성능 및 메모리 페널티가 제공됩니다. 또한 발신자가 구성 매개 변수에서 Unsorted 열거를 지정하면 발신자가 항목을 소비함에 따라 읽기 디렉토리가 게으르게 수행됩니다. 노드를 방문하기 전에 디렉토리의 즉각적인 후손을 정렬 할 필요가없는 특정 사용 사례가 존재하는 경우,이 라이브러리는 Unsorted 매개 변수가 true 로 설정되면 정렬 단계를 건너 뜁니다.
다음은 파일 시스템 계층을 비 결정적 순서로 가로 지르는 잠재적 인 Hazzards에 대한 흥미로운 읽기입니다. 당신이 해결하는 문제가 주문 파일의 영향을받지 않는다는 것을 알고 있다면, 당신은 당신이 Unsorted 사용하는 것을 권장합니다. 그렇지 않으면이 옵션을 건너 뜁니다.
연구자들은 파이썬 스크립트의 버그가 수백 개의 연구에 영향을 미쳤을 수 있습니다.
이 라이브러리는 자녀가 처리 한 후 각 디렉토리에 대해 호출 할 콜백 함수를 지정할 수있는 업스트림 코드를 제공합니다. 이는 파일 시스템을보다 효율적인 방식으로 이동 한 후 빈 디렉토리를 재귀 적으로 삭제하는 데 사용되었습니다. 이 사용법의 예는 examples/clean-empties 디렉토리를 참조하십시오.
이 라이브러리는 운영 체제가 반환하는 오류에 대해 호출 할 콜백을 지정할 수있는 업스트림 코드를 제공하므로 업스트림 코드는 다음에 수행 할 작업 코스를 결정할 수 있으며, 계층 구조를 중단할지 여부, 오류 콜백이 제공되지 않았거나 오류를 일으킨 노드를 건너 뛸 수 있습니다. 이 사용법의 예는 examples/walk-fast 디렉토리를 참조하십시오.