반응형
목표
저번에 만들었던 md2html 프로젝트에 고루틴을 적용하여 여러개의 파일을 변환할 수 있게 수정하겠습니다.
resource 폴더의 md파일의 구조를 다음과 같이 바꿔봅시다.
이렇게 바꾼 이유는 아래와 같습니다.
- deep3로 하위 폴더에 있는 test3.md도 바꾸는지 확인하기 위함
- deep1/deep로 중첩 폴더로 되어있는 test2.md도 바꾸는 지 확인하기 위함
- resource 폴더 바로 아래에 있는 test1.md도 바꾸는지 확인하기 위함
프로젝트 코드
코드가 많으로 코드 조각으로 나눠 적용하겠습니다.
모든 변경사항은 main.go 기준입니다.
main 함수의 변경과 구조체를 추가하겠습니다, 함수가 존재하지 않아 에러가 발생할 것입니다.
type file struct {
path string
name string
}
const (
resourcePath = "resource"
resultPath = "result"
)
...
func main() {
// 해당 경로에서 md 파일 목록을 가져옵니다
resourcePathList, err := getMdFileList(resourcePath)
utils.ErrorHandler(err)
// goroutine 을 기다리기 위해 WaitGroup 생성
wg := sync.WaitGroup{}
wg.Add(len(resourcePathList))
for _, resourceFile := range resourcePathList {
// 루프 캡처(반복문의 마지막 값으로 go가 실행됨)로 인해 복사본 생성
resourceFile := resourceFile
go func() {
// md 파일을 읽어서 HTML 파일로 변환하는 로직
err := md2html(resourceFile)
utils.ErrorHandler(err)
wg.Done()
}()
}
// goroutine 기다리기
wg.Wait()
fmt.Printf("Markdown to HTML")
}
전체적인 틀을 만들었습니다.
md 파일의 목록을 가져오고 이를 html로 바꾸는 작업을 고루틴으로 진행한 코드였습니다.
처음 만들 함수는 "getMdFileList"로 파라미터로 온 경로를 구준으로 하위의 모든 md 파일을 리스트로 추출합니다.
...
// getFileList : 파라미터 경로에서 부터 md 파일을 추출
func getMdFileList(root string) ([]file, error) {
fileList := []file{}
// root 경로에서 모든 파일 트리를 탐색하며 함수를 실행
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
// 해당 파일이 폴더가 아니고
if !info.IsDir() {
// md 확장자인 경우
mathed, _ := filepath.Match("*.md", filepath.Base(path))
if mathed {
fileList = append(fileList, file{path: path, name: info.Name()})
}
}
return nil
})
if err != nil {
return []file{}, err
}
return fileList, nil
}
...
md 파일을 html로 바꾸는 함수를 추가하겠습니다.
...
// md2html : md 파일을 읽어서 HTML 파일로 변환
func md2html(resourceFile file) error {
md := []byte(file2Text(resourceFile.path))
htmlBytes := mdToHTML(md)
resultFileName := strings.Replace(replaceFromEnd(resourceFile.path, resourceFile.name, ""), resourcePath, resultPath, 1) + replaceFromEnd(resourceFile.name, "md", "html")
// resultFileName 경로로 폴더가 없을 경우 생성
err := createFolderIfNotExists(resultFileName)
if err != nil {
return err
}
deleteFile(resultFileName)
byte2html(htmlBytes, resultFileName)
return nil
}
...
md2html 함수에서 사용할 뒤에서 부터 특정 문자열을 찾아 바꿔주는 함수 "replaceFromEnd"와
파일을 저장할 위치가 만약 폴더가 존재하지 않을 경우 만들어주는 "createFolderIfNotExists" 함수를 만들어줍시다.
...
// replaceFromEnd : 뒤에서 부터 old 를 찾아 new 로 변경
func replaceFromEnd(input, old, new string) string {
lastIndex := strings.LastIndex(input, old)
if lastIndex == -1 {
return input
}
return input[:lastIndex] + new
}
// createFolderIfNotExists : 폴더가 존재하지 않으면 생성
func createFolderIfNotExists(path string) error {
_, err := os.Stat(path)
if os.IsNotExist(err) {
// 0777 : 모든 권한 부여으로 파일 생성
// MkdirAll : 재귀함수로 부족한 모든 폴더 생섵
err := os.MkdirAll(path, os.ModePerm)
return err
}
if err != nil {
return err
}
return nil
}
...
이제 모든 코드를 넣었습니다.
결과물을 확인했습니다.
go run main.go
자 아래와 같이 파일이 만들어졌으면 성공입니다.
만약에 프로젝트가 실행되지 않으면 아래 깃허브 코드를 참고하시기 바랍니다.
https://github.com/DSeung001/learn-go/tree/master/md2html
반응형
'Go Lang > Study' 카테고리의 다른 글
[GoLang] 데드락, 라이브락, 기아상태 이해하기 (Deadlock, Livelock, Starvation) (1) | 2024.01.02 |
---|---|
[GoLang] Context가 뭘까요? (2) | 2023.12.02 |
[GoLang] Markdown을 HTML로 변환하기 (0) | 2023.11.05 |
[GoLang] Interface와 덕 타이핑 (0) | 2023.11.05 |
[GoLang] 단축 URL 웹사이트 만들기 (0) | 2023.11.03 |