0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go学習記録3日目 レスポンスタイムを計測するCLIツールの作成①

Posted at

Go言語学習の3日目です。

今日はWebサービスのレスポンスタイムを計測するCLIツールを作成しました。

作った機能

go run main.go と叩くと、レスポンスのステータスやレスポンスが返ってくるまでの時間を表示する機能を作りました。また、結果をjsonファイルに保存できるようにしました。

os.Argsによるコマンドライン引数の取得

前回Todoアプリを作成したときは、コマンドライン引数はflagパッケージで取得しました。今回は、os.Argsで取得しました。
想定では、go run main.go と叩いたとき、os.Args[0]でが取得できると考えていましたが、どうではありませんでした。

fmt.Printf("%v\n", os.Args) 
// go run main.go a b c
// 実行結果
// [C:\Users\R247E~1.SAD\AppData\Local\Temp\go-build1367157334\b001\exe\main.exe a b c]

go run main.goを実行した時、main.goを一時的なフォルダにビルドして、.exeを一時ファイルに出力、その.exeを即座に実行して、終わったら削除という流れになります。os.Args[0]はGoが一時的に作った.exeのパスになる(つまり、実行されたバイナリのパス)

作成したファイルと次回の課題

saveResultメソッドの条件分岐の書き方が適当になってしまった。あと、エラーメッセージをfmt.Errorfでラップしたい。また、ログファイルとしてログを出力させたい。
また、goroutineを使って、複数URLを並行チェックできるようにしたい。

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run main.go <URL>")
		return
	}

	url := os.Args[1]
	start := time.Now()

	resp, err := http.Get(url)
	elapsed := time.Since(start)

	if err != nil {
		fmt.Printf("[×]%s - Error: %s\n", url, err)
		return
	}
	defer resp.Body.Close()

	result := Result{
		Url:          url,
		ResponseCode: resp.StatusCode,
		StatusText:   http.StatusText(resp.StatusCode),
		ResponseTime: elapsed.Milliseconds(),
	}
	if err := saveResult(result); err != nil {
		log.Printf("Failed to save result: %v\n", err)
	}

	fmt.Printf("[✓]%s -%d %s -%dms\n",
		url,
		resp.StatusCode,
		http.StatusText(resp.StatusCode),
		elapsed.Milliseconds(),
	)

}

type Result struct {
	Url          string
	ResponseCode int
	StatusText   string
	ResponseTime int64
}

func saveResult(NewResult Result) error {
	var results []Result

	file, err := os.Open("results.json")

	if err != nil && os.IsNotExist(err) {
		os.Create("results.json")
	} else if err != nil {
		return fmt.Errorf("read error: %w", err)
	} else {
		defer file.Close()

		byteValue, err := io.ReadAll(file)
		if err != nil {
			return err
		}

		err = json.Unmarshal(byteValue, &results)
		if err != nil {
			return err
		}
	}

	results = append(results, NewResult)

	file, err = os.Create("results.json")
	if err != nil {
		return err
	}

	encoder := json.NewEncoder(file)
	return encoder.Encode(results)
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?