uokadaの見逃し三振は嫌いです

ここで述べられていることは私の個人的な意見に基づくものであり、私が所属する組織には一切の関係はありません。

Goで一定時間だけ立ち上がるサーバーを書いた

一定時間だけ立ち上がって自動的に終了するサーバーをGoで書いてみた。
あんまり用途はないのかもしれないが、例えばcronで毎日0:00から5分だけ立ち上がっていてそこにアクセスしてサーバーメトリクスを収集するみたいな使い方が出来るかもしれない。

いちおうコードの解説。
main関数のところだけコードをの詳細を書いてみる。
まずはじめに、runServer() でサーバーを立ち上げる。
次に、 time.Tick t で一定時間経過後にシグナルを送るようなselectループを作成する。
time.Tick et はただのデバッグ用のコードなので削除しても構わない。
最後に、 チャネル ch で入力を待って終了する。

func main() {
    go runServer()

    t := time.Tick(time.Duration(duration) * time.Second)
    et := time.Tick(time.Duration(1) * time.Second)
    go func() {
        for {
            select {
            case <-t:
                ch <- true
            case <-et:
                // debug code
                fmt.Printf("[%d] server running!\n", time.Now().Unix())
            }
        }
    }()
    _ = <-ch
    fmt.Println("Finished.")
}

試しに、3秒で終了するように動かしてた結果がこんな感じ。
きっちり、3回デバッグ用のコードが出力されて終了している。

% go run hey_server.go -duration=3
[1446923055] server running!
[1446923056] server running!
[1446923057] server running!
Finished.

以下、コード全体。

package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "time"
)

type BaseHandler struct {
    Name string
}

func (bh *BaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if bh.Name != "" {
        fmt.Fprint(w, "Hey "+bh.Name+"!")
    } else {
        fmt.Fprint(w, "Hey World!")
    }
}

func runServer() {
    mux := http.NewServeMux()
    bh := &BaseHandler{Name: name}
    mux.Handle("/hey", bh)

    addr := fmt.Sprintf(":%d", 8080)
    err := http.ListenAndServe(addr, mux)
    if err != nil {
        log.Fatal(err)
    }
}

var ch = make(chan bool)

var name string
var duration int

func init() {
    flag.StringVar(&name, "name", "", "your name")
    flag.IntVar(&duration, "duration", 60, "working time")
    flag.Parse()
}

func main() {
    go runServer()

    t := time.Tick(time.Duration(duration) * time.Second)
    et := time.Tick(time.Duration(1) * time.Second)
    go func() {
        for {
            select {
            case <-t:
                ch <- true
            case <-et:
                // debug code
                fmt.Printf("[%d] server running!\n", time.Now().Unix())
            }
        }
    }()
    _ = <-ch
    fmt.Println("Finished.")
}

// https://gobyexample.com/select

Link

uokada.hatenablog.jp