태그 보관물: go

Go언어 cron 처럼 스케줄링 하기

cron과 같은 유형의 스케줄러는 데이터 처리를 할 때 반드시 필요합니다.

데이터과학자들은 주로 젠킨스(Jenkins)나 airflow를 사용하겠지만 Python이나 Go로 직접 작성해야 하는 경우도 종종 생깁니다.

패키지 “github.com/jasonlvhit/gocron” 를 사용하는 방법입니다.

package main

import (
	"fmt"
	"github.com/jasonlvhit/gocron"
	"time"
)

func task() {
	fmt.Println("태스크를 실행합니다.")
}

func taskWithParams(a int, b string) {
	fmt.Println(a, b)
}

func main() {
	// 파라미터 없이 잡을 실행
	gocron.Every(2).Seconds().Do(task)
	gocron.Every(1).Minute().Do(task)
	gocron.Every(2).Minutes().Do(task)
	gocron.Every(1).Hour().Do(task)
	gocron.Every(2).Hours().Do(task)
	gocron.Every(1).Day().Do(task)
	gocron.Every(2).Days().Do(task)
	gocron.Every(1).Week().Do(task)
	gocron.Every(2).Weeks().Do(task)

	// 파라미터를 지정해서 잡을 실행
	gocron.Every(1).Second().Do(taskWithParams, 1, "hello")

	// 지정한 요일에 잡을 실행
	gocron.Every(1).Monday().Do(task)
	gocron.Every(1).Thursday().Do(task)

	// 지정한 시각에 잡을 실행 - 'hour:min:sec' - seconds optional
	gocron.Every(1).Day().At("10:30").Do(task)
	gocron.Every(1).Monday().At("18:30").Do(task)
	gocron.Every(1).Tuesday().At("18:30:59").Do(task)

	// Begin job immediately upon start
	gocron.Every(1).Hour().From(gocron.NextTick()).Do(task)

	// Begin job at a specific date/time
	t := time.Date(2019, time.November, 10, 15, 0, 0, 0, time.Local)
	gocron.Every(1).Hour().From(&t).Do(task)

	// NextRun은 다음번 실행될 시간을 알려줌
	_, time := gocron.NextRun()
	fmt.Println(time)

	// 지정한 태스크 제거
	gocron.Remove(task)

	// 모든 스케줄 작업을 제거
	gocron.Clear()

	// 모든 펜딩잡을 시작
	<-gocron.Start()

	// 새 스케줄러를 생성해서 동시에 2개의 스케줄러를 실행
	s := gocron.NewScheduler()
	s.Every(3).Seconds().Do(task)
	<-s.Start()
}

Go언어 csv.gz 한줄씩 읽어오기

Go언어로 CSV파일을 한줄씩 읽어오는 방법입니다.

파일을 메모리에 올려서 한 번에 처리하면 파일이 큰 경우에는 메모리를 다 쓰기 때문에 스왑을 사용해서 문제를 만듭니다.

조금 느리더라도 파일은 1줄씩 읽거나 조금씩 읽어야 합니다.

// csv.gz 파일에서 데이터를 한 줄씩 읽어오는 방법
package main

import (
	"compress/gzip"
	"encoding/csv"
	"fmt"
	"io"
	"log"
	"os"
	"strings"
)

func main() {
	file, err := os.Open("product_titles.csv.gz")

	if err != nil {
		log.Fatal(err)
	}

	defer file.Close()

	gzipReader, err := gzip.NewReader(file)

	if err != nil {
		log.Fatal(err)
	}

	defer gzipReader.Close()

	csvReader := csv.NewReader(gzipReader)
	csvReader.Comma = '\t'
	csvReader.FieldsPerRecord = -1

	for {
		record, err := csvReader.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}

		// 첫번째 필드만 꺼내오기
		fmt.Println("record count:", len(record))
		if len(record) < 1 {
			log.Println("record is empty")
			continue
		}
		field1 := strings.Trim(record[0], " ")
		if len(field1) < 1 {
			log.Println("field1 is empty")
			continue
		}

		fmt.Println("field1:", field1)
	}
}