Help us understand the problem. What is going on with this article?

goでcliツールを作ってみる

この記事はFusic Advent Calendar15日目の記事です。

こばんは。お久しぶりです。まっさんです。
アドベントカレンダー何を書こうか迷っていたら、こんな時間になっていまいました。良い子はちゃんと事前に準備しときましょう。

とくに何も閃かなかったので、弊社の一部のメンバーで行っている朝の15分輪読会で、絶賛勉強中のgo言語について書いてみようと思います。(golang初学者ですので、誤り等ありました。ご指摘いただければ幸いです)

社内のニコニコカレンダーのcliツールを作ってみる

弊社には、@Y_uuu が作成した、nicoleというニコニコカレンダーがあります。
社員の20〜50%が日々投稿する人気ツールです。
そんなニコニコカレンダーのcliツールを作ってみました。リファクタリングとか、してないので、色々ツッコミどころ満載ですが、こんな感じです。

package main

import (
    "bufio"
    "bytes"
    "encoding/json"
    "flag"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "time"
)

type PostData struct {
    Mood    string `json:"mood"`
    Message string `json:"message"`
    Date    string `json:"date"`
}

func main() {
    postJson := createJson()
    if postJson == nil {
        return
    }
    key := getEnvKey()

    req, err := http.NewRequest("POST", "{{ ニコニコカレンダーのAPIのURL }}", bytes.NewBuffer(postJson))
    req.Header.Set("API-KEY", key)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Sprintf("req err: %s", err)
    }
    defer resp.Body.Close()

    respBody, err := ioutil.ReadAll(resp.Body)
    if err == nil {
        fmt.Sprintf("resp err: %s", err)
    }
    fmt.Println(string(respBody))
}

func createJson() []byte {
    t := time.Now()
    defaultMood := "normal"
    defaultMessage := "普通"
    mood := flag.String("mood", defaultMood, "気分")
    key := flag.String("api_key", "", "あなたのApiキーを入力して下さい。")
    message := flag.String("message", defaultMessage, "今日の一言")
    date := flag.String("date", t.Format("2006-01-02"), "日時")
    flag.Parse()

    if *key != "" {
        setEnvKey(*key)
        return nil
    }
    postData := PostData{*mood, *message, *date}
    outputJSON, err := json.Marshal(&postData)
    if err != nil {
        fmt.Sprintf("json err: %s", err)
    }
    return outputJSON
}

func setEnvKey(key string) {
    file, err := os.Create(`./.env`)
    if err != nil {
        fmt.Sprintf("create file err: %s", err)
    }
    defer file.Close()
    output := key
    file.Write(([]byte)(output))
}

func getEnvKey() string {
    file, err := os.Open("./.env")
    if err != nil {
        fmt.Sprintf("open file err: %s", err)
    }
    defer file.Close()

    var envKey string
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        line := scanner.Text()
        envKey = line
    }
    if err := scanner.Err(); err != nil {
        fmt.Sprintf("read file err: %s", err)
    }
    return envKey
}

躓いたポイント

社内のニコニコカレンダーのAPIを叩くために、マイページで作成した API_KEY が必要になります。
ファイルに書き出すよりも、環境変数にセットしたかったので、ググったところ、osパッケージをインポートすると、いい感じに環境変数の読み取り、書き込みができるとのこと。
こんな感じ。

読み取り

package main

import (
    "fmt"
    "os"
)

func main() {
    val := os.Getenv("HOGE")
    fmt.Println(val)
}

設定されてない場合は、空文字が返ります。

書き込み

package main

import (
    "fmt"
    "os"
)

func main() {
    os.Setenv("HOGE", "hoge_value")
}

とても、簡単ですね。しかし、いざ使ってみると、上手くAPI_KEYが取得できない。

どうも、Goの動いているプロセスに対して、環境変数がセットされるようで、そのプロセスが死ぬの環境変数も消えてしまう?っぽい。(間違っていたらすみません。)

外部コマンドに頼る

osパッケージを使って環境変数にセットしよう作戦はあえなく、失敗したので、Goからexport HOGE=hogeのようにosのコマンドを呼び出して無理やり環境変数を設定したいと思います。
os/exec パッケージを使用して外部コマンドを実行できるようです。こんな感じ。

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    out, err := exec.Command("ls", "-la").Output()
    if err != nil {
        fmt.Println(err)
    }

    fmt.Printf(string(out))
}

exec.Command で環境変数をセットしようとしたのですが、こちらは

exec: "export": executable file not found in $PATH

とエラーになり上手く行かず。(理由もまだわかって何ので、わかったら追記します。。。)

おとなしくドットファイルに書き込む

環境変数にセットするのは、上手く行かなかったので、おとなしくドットファイルを作成して、そこで書き込みと読み取りを行うことにしました。

終わりに

まだまだ、Goっぽい書き方とかGoの良さが活かせていないので、日々の輪読をとして精進しようと思います。

明日は、 @yoshitake_1201 の投稿ですので、皆様お楽しみにー!!!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした