Go開発者への道 第4回 cobraとviperの使い方

GOコラム

Go初心者向けに始めた記事の第4回になります。
Go初学者がアプリ開発する時に「アプリの起動はビルドファイルを実行するだけでよいのか?」「アプリ起動する時に必要な設定とかはどうするか?」など疑問がうまれると思います。
自分の開発している現場では、基本的にアプリの起動はcobraのCLIを使っていて、環境変数の設定はviperを使用してます。なのでcobra、viperはGo開発者にとって必要な知識になります。

cobra、viperについて

cobraとは

cobraは簡単にCLIを実装できるライブラリ、以下のリンクに書いてあるようにKubernetesにも使われていります。

GitHub - spf13/cobra: A Commander for modern Go CLI interactions
A Commander for modern Go CLI interactions. Contribute to spf13/cobra development by creating an account on GitHub.

cobraを使用している理由として、ビルドした1つのバイナリで複数の処理ができることです。
例えば、APIと定期的にバッチを実行する処理2つを別コマンドで動かしたい時に、CLIだとサブコマンドを使用して、APIの起動とバッチの起動を分けることができます。そして起動する時にコマンドのオプションをつけたい場合にも、flagを使用することで容易にできます。

viperとは

環境設定ファイルを簡単にするライブラリ。Viperは様々な設定のニーズとフォーマットに対応し、JSON, TOML, YAMLなどからファイルを読み込んで環境の設定ができる。

GitHub - spf13/viper: Go configuration with fangs
Go configuration with fangs. Contribute to spf13/viper development by creating an account on GitHub.

cobra、viperを試してみる

インストール

# ライブラリをインストール
go get -u github.com/spf13/cobra@latest

# cobraのCLIをインストール
go install github.com/spf13/cobra-cli@latest

# viperのインストール
go get github.com/spf13/viper

# cobraアプリの初期化をして、実行に必要なファイルが生成されます。
# 色々ファイルが作成されていますが、とりあえずmain.go、cmd/root.goだけを気にしておけば良いです。
cobra-cli init

コード

今回はお試してとして、default.toml or test.tomlのファイルを読み込み、読み込んだ内容を出力するソースを書きました。
tomlファイルの内容は今後DBに接続する時に使用する予定です。
このソースの処理の流れとして、

  • init()で初期化処理が動き
  • initConfig()で設定ファイルを読み込み、configに設定する
  • Execute() からRun: func(~)が呼ばれ、configの中身が出力

という流れになってます。

src/cmd/root.go

/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
	"log"
	"os"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

type Config struct {
	Type     string
	Host     string
	Port     int
	User     string
	Password string
	Name     string
}

var config Config

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use: "go-column",
	Run: func(cmd *cobra.Command, args []string) {
		// configの中身を出力
		log.Printf("configの中身:{type: %s, host: %s, port: %d, user: %s, pass: %s, name: %s}",
			config.Type, config.Host, config.Port, config.User, config.Password, config.Name)
	},
}

func Execute() {
	err := rootCmd.Execute()
	if err != nil {
		os.Exit(1)
	}
}

func init() {
	// 初期化処理
	// configの設定
	rootCmd.Flags().StringP("configName", "n", "default.toml", "config file name")

	// Runを実行するたびに、initConfigを呼び出す。その後に、Runの処理が動き出す。
	cobra.OnInitialize(initConfig)
}

func initConfig() {
	configName, _ := rootCmd.Flags().GetString("configName")
	viper.SetConfigFile(configName)

	// 設定ファイルを読み込む
	if err := viper.ReadInConfig(); err != nil {
		log.Println(err)
		os.Exit(1)
	}

	// 設定ファイルの内容を構造体に設定
	if err := viper.Unmarshal(&config); err != nil {
		log.Println(err)
		os.Exit(1)
	}
}

test.toml

type = "mysql"
host = "localhost"
port = 3306
user = "root"
password = "test_pass"
name = "test"

default.toml

type = "mysql2"
host = "localhost2"
port = 3307
user = "default"
password = "default_pass"
name = "default"

Dockerfile

コンテナあげる度に、cobra-cliをインストールする必要があるので、イメージを作成する。

FROM golang:1.19-bullseye
WORKDIR /work

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        wget \
        make \
        unzip \
        git \
        clang-format \
        vim \
    && apt-get clean

# cobraのCLIをインストール
RUN go install github.com/spf13/cobra-cli@latest

RUN pwd
COPY src/go.mod src/go.sum ./
RUN go mod download && go mod verify

docker-compose.yml

Dockerfileで作成したイメージを見るように修正

version: "3.9"
services:
  go-env:
    build:
      context: .
    volumes:
        - ./src:/work
    working_dir: /work
    tty: true

最終的には以下のようなファイル構成になります。

GitHub - SND1231/go-column at go-column-4
Go コラムのサンプルコードをこちらに残す. Contribute to SND1231/go-column development by creating an account on GitHub.

実行結果

フラグの設定がなければ、default.tomlの内容が出力され、フラグが設定されていれば設定されたファイルの内容が出力されてます。

# build
root@80eba8a81cb8:/work# make build
go build .

# フラグなしで、default.tomlの内容が読み込まれていることを確認
root@80eba8a81cb8:/work# ./go-column                       
2023/05/24 13:11:08 configの中身:{type: mysql2, host: localhost2, port: 3307, user: default, pass: default_pass, name: default}

# フラグにtest.tomlを設定して、test.tomlファイルの内容が読み込まれていることを確認
root@80eba8a81cb8:/work# ./go-column --configName test.toml
2023/05/24 13:12:21 configの中身:{type: mysql, host: localhost, port: 3306, user: root, pass: test_pass, name: test}

まとめ

今回はcobra、viperについて説明をしてきました。
次はGoでAPIを作る方法を紹介していきます。Goの場合はフレームワークを使用せずAPIの開発をすることができるので、その理由とどのように開発をしているか書いてます。興味あればぜひ読んでください。
今回の記事以外にもGoについて書いた記事がございますので、もし興味がありましたら、おすすめ記事も見てもらえたらと思います。

【次の記事】

【おすすめ記事のリンク】


コメント

タイトルとURLをコピーしました

Fatal error: Uncaught JSMin_UnterminatedStringException: JSMin: Unterminated String at byte 733: "自分の働いている会社では、GoのWebアプリケーションを作る際に、cobraとviperを使います。 in /home/c5287456/public_html/engineer-want-to-grow.com/wp-content/plugins/autoptimize/classes/external/php/jsmin.php:214 Stack trace: #0 /home/c5287456/public_html/engineer-want-to-grow.com/wp-content/plugins/autoptimize/classes/external/php/jsmin.php(152): JSMin->action(1) #1 /home/c5287456/public_html/engineer-want-to-grow.com/wp-content/plugins/autoptimize/classes/external/php/jsmin.php(86): JSMin->min() #2 /home/c5287456/public_html/engineer-want-to-grow.com/wp-content/plugins/autoptimize/classes/external/php/ao-minify-html.php(257): JSMin::minify('{"@context":"ht...') #3 [internal function]: AO_Minify_HTML->_removeScriptCB(Array) #4 /home/c5287456/public_html/engineer-want-to-grow.com/wp-content/plugins/autoptimize/classes/external/php/ao-minify-html.php(108): preg_replace_callback('/(\\s*)(<script\\. in /home/c5287456/public_html/engineer-want-to-grow.com/wp-content/plugins/autoptimize/classes/external/php/jsmin.php on line 214