안녕하세요.
갈비만두를 좋아하는 개발자 임태빈입니다.
이번 포스팅에서는 Go의 Channel과 goRoutine을 활용해서
로그 파싱 파이프라인을 만들어보려고 합니다.
코드는 매우 간단하며 전체 코드 공유 후, 함수 설명을 간단하게 해보도록 하겠습니다:)
package main
import (
"fmt"
"log"
"os"
"regexp"
"strings"
)
func PrintData(data string) <-chan string {
oc := make(chan string)
go func() {
oc <- data
close(oc)
}()
return oc
}
func ExtractRegexpData(ic <-chan string) <-chan string {
oc := make(chan string)
go func() {
for data := range ic {
re1, err := regexp.Compile("\\w+/\\w+/\\w+ \\w+:\\w+:\\w+ - ")
if err != nil {
panic(err)
}
regexpRemoveText := re1.FindString(data)
//fmt.Println(regexpRemoveText)
//fmt.Println(data)
extraText := strings.Replace(data, regexpRemoveText, "", 1)
//fmt.Println(extraText)
oc <- extraText
}
close(oc)
}()
return oc
}
func WriteFile(ic <-chan string) <-chan string {
oc := make(chan string)
var f *os.File
var err error
f, err = os.OpenFile("data.txt", os.O_RDWR|os.O_CREATE, 0755)
f.Seek(0, 2)
if err != nil {
log.Fatal(err)
}
defer f.Close()
for data := range ic {
data_byte := []byte(data + "\n")
_, err = f.Write(data_byte)
if err != nil {
panic(err)
}
}
return oc
}
func PrintChanData(ic <-chan string) {
for data := range ic {
fmt.Println(data)
}
}
func main() {
str1 := "2022/01/03 09:53:27 - 123123"
PrintChanData(ExtractRegexpData(PrintData(str1)))
WriteFile(ExtractRegexpData(PrintData(str1)))
}
메인 코드에서는 파이프라인 코드를 두개 돌렸습니다.
하나는 값을 console창에서만 출력하는 것이고 다른 하나는 파일에 데이터를 Write해주는 것입니다.
자세한 내용은 함수 설명에서 해보도록 하겠습니다.
func PrintData(data string) <-chan string {
oc := make(chan string)
go func() {
oc <- data
close(oc)
}()
return oc
}
PrintData 함수에서는 입력 받은 데이터를 출력하고 채널에 넣어서 다른 goRoutine에 넘겨주는 함수입니다.
func ExtractRegexpData(ic <-chan string) <-chan string {
oc := make(chan string)
go func() {
for data := range ic {
re1, err := regexp.Compile("\\w+/\\w+/\\w+ \\w+:\\w+:\\w+ - ")
if err != nil {
panic(err)
}
regexpRemoveText := re1.FindString(data)
extraText := strings.Replace(data, regexpRemoveText, "", 1)
oc <- extraText
}
close(oc)
}()
return oc
}
ExtractRegexpData함수는 PrintData로 부터 받은 채널에서 값을 꺼네 정규표현식을 활용해 메시지만 추출을 진행합니다. 추출한 데이터를 다시 채널에 넣어서 다른 goRoutine 함수에 보내줍니다.
func PrintChanData(ic <-chan string) {
for data := range ic {
fmt.Println(data)
}
}
PrintChanData함수는 추출한 데이터를 출력해주는 함수입니다.
func WriteFile(ic <-chan string) <-chan string {
oc := make(chan string)
var f *os.File
var err error
f, err = os.OpenFile("output.txt", os.O_RDWR|os.O_CREATE, 0755)
f.Seek(0, 2)
if err != nil {
log.Fatal(err)
}
defer f.Close()
for data := range ic {
data_byte := []byte(data + "\n")
_, err = f.Write(data_byte)
if err != nil {
panic(err)
}
}
return oc
}
WriteFile함수는 추출한 데이터를 파일에 저장하는 함수입니다. 여기서 파일을 생성해주는 부분은 os.OpenFile입니다. 만약 os.O_CREATE가 없다면 파일 생성이 되지 않아 에러가 발생합니다. 파일이 기존에 있다면 에러가 발생하지 않습니다. 이 부분만 주의하신다면 문제 없이 코드를 사용하실 수 있을 거라 생각합니다.
이번 포스팅에 준비한 것은 이걸로 끝입니다:) goRoutine이 아직 익숙치가 않아서 자꾸 실수를 할 때도 있었지만 코드를 구현해보면서 고가 정말 재밌다고 생각이 들었습니다 ㅎㅎ
궁금하신 부분이 있다면 댓글로 남겨주시면 감사드리겠습니다!!