특정 디렉토리에 log 파일이 쌓인다면 해당파일을 분석하고 처리 및 저장하는 기능이 필요하다고 가정해보자
package main
import (
"fmt"
"os"
"sync"
"strconv"
)
const store_path = "/home/smsc/sim/go/src/monitoring/store_dir"
var ch = make(chan string, 100)
func check(err error) {
//go 내장 함수로 호출이 되면 해당 함수는 즉각 멈추고 나머지 defer들을 호출하고 리턴이 되며 이는 상위 콜스택을 따라 올라가가게 되며 마지막은 프로그램이 종료되게 된다.
if err != nil {
// log.Fatal(err)
//panic(e)
// fmt.Println("error : ", e)
}
}
func createFile(name string, ch chan string) {
for prefix_name := 0; prefix_name < 5; prefix_name++ {
err := os.WriteFile(name + "/file" + strconv.Itoa(prefix_name), []byte("content" + strconv.Itoa(prefix_name)), 0644)
check(err)
// fmt.Println("create file" + name)
// time.Sleep(time.Second * 1) //초에 한번씩 파일 생성
}
// close(ch)
}
func sendAllFile(mpath, spath string, file_name string) {
fmt.Println("send : ", spath + "/" + file_name)
err := os.WriteFile(spath + "/" + file_name, []byte("content" + file_name), 0644)
check(err)
path_err := os.Remove(mpath + "/" + file_name)
check(path_err)
}
func checkDir(path string, ch chan string) {
files, err := os.ReadDir(path)
check(err)
if files != nil {
for _, file := range files {
ch <- file.Name()
}
} else {
fmt.Println("dir empty!")
}
// time.Sleep(time.Second)
}
func controlFile(path string, ch chan string) {
for {
select {
case file_name := <- ch:
sendAllFile(path, store_path, file_name)
default :
checkDir(path, ch)
}
// time.Sleep(time.Second)
}
}
func main() {
monitoring_path := os.Getenv("MONITORINGPATH")
fmt.Println("monitoring path : ", monitoring_path)
//monitoring dir 생성
err := os.Mkdir(monitoring_path, 0755)
check(err)
err = os.Mkdir(store_path, 0755)
check(err)
//파일 생성하고 ch에 해당 파일 이름 넣기
var wg sync.WaitGroup
wg.Add(1)
go controlFile(monitoring_path, ch)
go createFile(monitoring_path, ch)
// defer os.RemoveAll(store_path)
wg.Wait()
}
select는 Goroutine이 다중 커뮤니케이션 연산에서 대기할 수 있게 하기 때문
때문에 switch처럼 참거짓으로 case를 나눌 수 없고 위처럼 channel 연산으로 가능하다.