UdemyでGo言語入門:簡単なHTTPリクエストで洒脱な始業連絡を実装!


はじめに

簡単に自己紹介

  • 私は普段はメカ物設計に携わるノンプログラマーです。
  • ここ数年、業務でPythonを使うようになったのを皮切りにプログラミングを学習し、自宅用に使う謎アプリから、webサービス開発(⇒頓挫)と、趣味に花を咲かせています。
  • プログラミング学習って、基礎的な構文なんかは本やネット記事を読んだりすれば分かるのですが、実践的なテクニックだったり、複数言語を組み合わせて使うケースになると、途端に学習のハードルが上がるなぁ…と悩んでいた折、Udemyさんの様々な講座を発見し、それ以来(セールのたびに)お世話になっております…!

なぜGo言語を学ぼうと思ったか

  • Go言語自体の特徴は、こちらの記事がまとめて下さっています
  • Python一辺倒だった私個人にとっては、「記述の自由度が少ない=良いコードの書き方に迷いが少ない」ことや「コンパイル型言語だから成果物を周囲に展開しやすい」ことが新鮮に感じられ、学習意欲を駆り立てられました。
  • あとGopherがかわいい


出典:https://golang.org/doc/gopher/

今回何を作ったか

Microsoft Teamsのチャネル上に、私の行きたい温泉地の写真を付けて洒脱に始業連絡を行います…!
何の実益もないです!

※この写真は今回解説用に私が撮った写真を使用しています

モチベーションの補足

  • 私の勤める会社では、リモートワーク普及時に「上司に始業・終業を連絡する」というルールが敷かれました…。
  • Teamsのチャットで毎回「おはようございます、始業します」って打つのも面倒なんですよね…。そこから何か会話するわけでも無いですし。
  • じゃあTeamsに始業連絡を投稿するプログラムを作って、それを走らせれば良いんじゃない?
  • そこまでするなら何か遊び心を出していきたいもんだ…。よし、温泉画像を貼って癒されよう

いざ実装

方針検討

Microsoft TeamsにはIncoming Webhook機能があり、Webhookに所定のjson形式データを送ることで「カード」なるものを投稿できることは知っていました。

出典:Microsoft様公式HP

webhookとは所定のURLにリクエストをPOSTするようなもののようです。そこで冒頭に紹介した講座で習得した、JSON形式の扱いや、HTTPリクエストの投げ方を活用して実装していきます。

機能設計

  1. 本文は固定する(タイトル:氏名、サブタイトル:おはようございます、始業します)
  2. 温泉地画像はネット上の使って良い画像を使用する。毎日同じではつまらないから、いくつかの候補からランダムで選択する。

ファイル構成

main.go
spas.json
ファイル 説明
main.go その名の通りメイン
spas.json 温泉の名前と画像URLをまとめたjsonファイル

ソースコード

main.go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "math/rand"
    "net/http"
    "time"
)

var apiURL string = "<YOUR WEBHOOK URL>"

type heroCard struct {
    Type        string        `json:"type"`
    Attachments []interface{} `json:"attachments"`
}

type heroAttachments struct {
    ContentType string      `json:"contentType"`
    Content     heroContent `json:"content"`
}

type heroContent struct {
    Title    string        `json:"title"`
    Subtitle string        `json:"subtitle"`
    Text     string        `json:"text"`
    Images   []interface{} `json:"images"`
}

type spa struct {
    Title string `json:"title"`
    Image string `json:"image"`
}

func jsonReader(file string) []spa {
    bytes, err := ioutil.ReadFile(file)
    if err != nil {
        log.Fatal(err)
    }

    var spas []spa
    if err := json.Unmarshal(bytes, &spas); err != nil {
        log.Fatal(err)
    }

    return spas
}

func createRand(size int) int {
    rand.Seed(time.Now().UnixNano())
    return rand.Intn(size)
}

func createHero(name, msg, text, image string) heroCard {
    hero := heroCard{
        Type: "message",
        Attachments: []interface{}{
            heroAttachments{
                ContentType: "application/vnd.microsoft.card.hero",
                Content: heroContent{
                    Title:    name,
                    Subtitle: msg,
                    Text:     text,
                    Images: []interface{}{
                        map[string]string{
                            "url": image,
                        },
                    },
                },
            },
        },
    }

    return hero
}

func main() {
    spas := jsonReader("./spas.json")
    spa := spas[createRand(len(spas))]

    heroStr, _ := json.Marshal(createHero("Tenkoh", "おはようございます、始業します", spa.Title, spa.Image))

    resp, err := http.Post(apiURL, "application/json", bytes.NewBuffer(heroStr))
    if err != nil {
        fmt.Println("Error")
    }
    defer resp.Body.Close()

    fmt.Println(resp.Body)
}

spas.json
[
    {"title":"石見銀山温泉", "image":"URL1"},
    {"title":"草津温泉", "image":"URL2"},
    {"title":"別府温泉", "image":"URL3"},
    {"title":"有馬温泉", "image":"URL4"},
    {"title":"奥飛騨温泉", "image":"URL5"}
]

解説

Webhook URLの取得

  • こちらはたくさん記事がありますので割愛します。

カードを作るための構造体の作成

  • 上記で取得したwebhookに、カードを作るための情報をjsonにして渡す必要があります。ベストプラクティスはよく分からないのですが、講座の中では構造体をマーシャルしていたので、まずはそれに倣ってみます。
  • 渡すべきjsonの形式ですが、Microsoftさんの公式ホームページを見てもイマイチ分かりません…。ネットの海を漂った結果、Hiro様の素晴らしい解説記事にたどり着きました!そちらで知った情報をもとに、大きめの画像が配置されるヒーローカードを作っていきます。
  • いかんせんネストした構造体になりそうですので、初学者である私はheroCard heroAttachments heroContent の3つの構造体に分割して堅実に進めてみます。
  • ただ、構造体を定義する作業はめっっっっっちゃ面倒です。 今回は修行だと思い手打ちしていきましたが、講座の中で教えてくれるjsonからGo Structに変換してくれるサイトを活用することを推奨します!! (JSON-to-Go) こういう実践テクニックを教えてくれるのも助かりますね

HTTPリクエストの送信

  • HTTPリクエストの送信には様々な種類があり、講座の中でもいろいろなパターンを教えて貰えます。
  • 今回はシンプルに http.Post でPOSTしていきます。

結果

  • こんな感じのカードがTeamsチャネルに投稿されました。温泉行きたいですね。
  • 私は上記プログラムをコンパイルした.exeファイルを、こちらの方法でスピーディーに呼び出すように活用しています。

おわりに

  • 講座で学んだ内容を使って、どうでもいいソフトを作ることができました!
  • 今回はHTTPリクエストだけを活用しましたが、講座の主題はサーバ側(API)の作成なので、そちらも自分なりのテーマを創出し、その中で技術を身に着けていきたいと思っています。

補足情報

  • 私はWebの仕組みも良く分からなかったので、こちらの書籍を自習して補いました。