Go と LINE BOT に まとめて入門する

4cd9f68f08d2200de34043e4ce049d03?s=47 yagi_eng
November 04, 2020

Go と LINE BOT に まとめて入門する

以下イベントの登壇資料です

https://linedevelopercommunity.connpass.com/event/192599/

4cd9f68f08d2200de34043e4ce049d03?s=128

yagi_eng

November 04, 2020
Tweet

Transcript

  1. GoとLINE BOTに まとめて入門する やぎぬ(@yagi_eng) 2020/11/04 1 The Go gopher was

    designed by Renée French. Licensed under the Creative Common 3.0 Attributions License.
  2. ゆるくやっていきましょ • 時間的に全然ごはん食べたり飲んだりしながら聞いて頂いてOKです • 堅苦しいの好きじゃないので、ゆるくやっていきましょう! 2

  3. アジェンダ • 登壇者の自己紹介 • こんなの作ります • このイベントの進め方 • このイベントのゴール •

    レクチャ • レクチャのアジェンダはレクチャ直前にて 3
  4. 登壇者の自己紹介 4

  5. 名前 Yaginuma Kohei(あだ名:やぎぬ) 経歴 大手SIerでクラウドエンジニア⇒フリーWebエンジニア 最近興味があること 個人サービス開発、 LINEbot&ミニアプリ、Go、マネジメント、コーチング、etc… 趣味 海外旅行、ランチ巡り、水泳、ミュージカル鑑賞、ゲーム、

    なんか面白そうなこと、etc… 5 やぎぬ
  6. 6 • 2020/9 大阪・滋賀 • 2020/3 セブ • 2020/2 台湾

    • 2019/8,9 東南アジアバックパック • 2019/8 北海道 • 2018/11 東北周遊 • 2018/9 カンボジア・ベトナム • etc… Instagramにいっぱい 旅行の写真載せてます! https://www.instagram.com/yaginu_travels_around/ 旅行好きです
  7. 7 中目黒・渋谷あたりでよくランチ 食べてます Instagramにいっぱい ランチの写真載せてます! https://www.instagram.com/yaginu_nakame_lunch/ 食べるのも好きです

  8. 上田さん 8 コミュニティ活動 Google Developer Expert (Go) Go ビギナーズ Go

    Conference @tenntenn https://tenntenn.dev
  9. こんなの作ります 9

  10. 10 こちらのQRコードを LINEで読み取るとお手元の 端末でお試し頂けます サンプル

  11. 説明 11 今回やること • 位置情報を送信すると、その周辺の飲食店を返すBOTの作成 やらないこと • お気に入り機能 • 文字検索

    • LIFF 技術的な補足 • 飲食店検索にはホットペッパーAPIを使います • 先ほどのサンプルではGoogleMapsAPIを使っていますが、 ホットペッパーAPIの方がカジュアルに使えます
  12. このイベントの進め方 12

  13. StepByStepで解説していくスタイル • いきなり目的のBOTを作るのはハードル高いしごちゃごちゃしてしまうので、 hello worldからはじめて5ステップに分けて解説していきます 13

  14. Excuse • カジュアルに参加頂けるように1時間という時間枠でやっています • Goでの開発やLINE BOT開発の流れを理解して頂きたいというのが趣旨です • 文法については体系立ててレクチャせず、かいつまんでレクチャしていきます • オンライン形式や限られた時間枠ということを踏まえ、ハンズオン形式や

    ライブコーディング形式ではなく、講義形式で行います 14
  15. このイベントのゴール 15

  16. GoとLINE BOTの初歩的なことがわかる • Goの基本事項がわかる • LINE BOT SDKの使い方がわかる • 「よし、GoやLINEBOTに触ってみよう」と思える

    16
  17. レクチャ 17

  18. レクチャのアジェンダ • LINE BOTの概要 • Goの概要 • 実装&解説 18

  19. LINE BOTの概要 19

  20. Messaging API • LINE BOTっていうけど正確にはMessagingAPI • 以下公式より引用 • Messaging APIを使って、ユーザー個人に合わせた体験をLINE上で提供する

    ボットを作成できます。 • 作成したボットは、LINEプラットフォームのチャネルに紐づけます。 • Messaging APIを使って、ボットサーバーとLINEプラットフォームの間で データを交換できます。リクエストは、JSON形式でHTTPSを使って送信さ れます。 引用元 https://developers.line.biz/ja/docs/messaging-api/overview 20
  21. Messaging APIの仕組み(公式から引用) 1. ユーザーが、LINE公式アカウントにメッセージを送信します。 2. LINEプラットフォームからボットサーバーのWebhook URLに、 Webhookイベントが送信されます。 3. Webhookイベントに応じて、ボットサーバーからユーザーに

    LINEプラットフォームを介して応答します。 21
  22. Goの概要 22

  23. Goとは? 23 Googleが開発したプログラミング言語 • 2009年11月に最初のバージョンをオープンソースで公開 • 2012年3月に正式バージョンであるGo1.0を公開 • 2020年11月現在の最新バージョンはGo1.15 •

    半年毎のペースでバージョンアップ • Robert Griesemer、Rob Pike、Ken Thompsonによって設計された 特徴 • 強力でシンプルな言語設計と文法 • 並行プログラミング • 豊富な標準ライブラリ群 • 周辺ツールの充実 • シングルバイナリ・クロスコンパイル 上田さん資料 より抜粋
  24. Goが開発された理由 24 Google内の課題を解決するために開発された • 開発速度の低下 • 超巨大なコードベース • 複雑な依存関係 •

    マルチコア時代のシステム言語 • 並行処理とガベージコレクタを同時に採用 • 軽量プログラミング言語(LL, Light weight Language)の盛り上がり • 静的型付け言語だとコンパイル時にエラーが発見できる • 動的型付け言語だと書きやすい • いいところ取りの書きやすい静的型付け言語がない • 静的解析がしやすい言語 • 言語設計のレベルで静的解析しやすい言語を目指した 上田さん資料 より抜粋
  25. Goの特徴 − 周辺ツールの充実 − 25 • go toolとして標準/準標準で提供 • サードパーティ製のツールも充実

    • IDEによらない独立したツールとして提供 go build ビルドを行うコマンド go test xxxx_test.goに書かれたテストコード の実行 go doc, godoc ドキュメント生成 gofmt, goimports コードフォーマッター go vet コードチェッカー gopls Language Server Protocol (LSP) の実装 上田さん資料 より抜粋
  26. インストール 26 必要に応じて、以下の記事を参考にインストールしてください 【超簡単】GoのインストールとVSCode設定方法 https://qiita.com/yagi_eng/items/69cb75cd3062a24888ac

  27. 実装&解説 27

  28. こんな感じで実装していきます! 1. まずはHello, World! 2. オウム返しのLINEBOT 3. 位置情報から緯度/経度を返すLINEBOT 4. 位置情報から周辺の飲食店を返すLINEBOT

    5. 位置情報から周辺の飲食店を見やすく返すLINEBOT 28
  29. リポジトリはこちら https://github.com/yagi-eng/go-linebot-start ⇒ステップ毎にブランチを作成しています、インデント下がりがブランチ名 1. まずはHello, World! • hello-world 2. オウム返しのLINEBOT

    • parrot 3. 位置情報から緯度/経度を返すLINEBOT • latlng 4. 位置情報から周辺の飲食店を返すLINEBOT • resto 5. 位置情報から周辺の飲食店を見やすく返すLINEBOT • carousel 29
  30. このレクチャで出てくるけど触れない要素 Goに興味を持って独学される際には以下も参考にしてみてください あまり一度に情報詰め込み過ぎるとパンクするので。。 • パッケージ管理・インポート • exported・unexported宣言 • エラー処理 •

    変数宣言における_(ブランク変数) • 配列とスライス • ポインタ 30
  31. 1.まずはHello, World! 31

  32. できあがり 32 localhost:8080にアクセスしたら Hello, Worldと表示されるように実装します

  33. 実装 33 main関数 • 最初に実行される関数 • 厳密には初期化後に実行される 関数宣言 • 18-21行目参照(返り値なし)

    • 返り値ありは後述 変数宣言 • 19行目参照 • 他にも色んな宣言の仕方がある • 型推論がある • 右辺から判断して自動で型付け
  34. 実装 34 ハンドラ登録 • 11行目参照 • 「このURLにアクセスしたら、この関数を 実行しますよ」の登録 • 11行目ではルートドメインにアクセスした

    らhelloHandlerが実行されるように登録 • localhost:8080/helloとしたければ、 http.HandleFunc(“/hello”, helloHandler) とする HTTPサーバの起動 • 15行目参照
  35. 35 サーバ立てるのめっちゃ楽

  36. 実行 36 以下のコマンドを実行する $ go run (実行するGoファイルのパス) または $ go

    run (実行するGoファイルのディレクトリパス) e.g. $ ls main.go $ go run main.go または $ go run .
  37. 【再掲】できあがり 37 localhost:8080にアクセスしたら Hello, Worldと表示されるように実装します

  38. 2.オウム返しのLINEBOT 38

  39. できあがり 39 送信した内容をそのままオウム返しする LINE BOTを作成します

  40. 差分 40 https://github.com/yagi-eng/go-linebot-start/compare/hello-world...parrot

  41. LINE Developersに登録 41 以下の公式サイトを参考にアカウントやチャネルを作成する ・Messaging APIを始めよう ⇒LINE Developersコンソールでチャネルを作成する https://developers.line.biz/ja/docs/messaging-api/getting-started/ ・ボットを作成する

    ⇒LINE Developersコンソールでボットを設定する https://developers.line.biz/ja/docs/messaging-api/building-bot/ ※チャネル: 「BOTを管理するもの」くらいの認識でOKです
  42. LINE Developersでシークレットを取得 42 LINE Developersの各チャネル画面のBasic settingsの下の方にあります

  43. LINE Developersでアクセストークンを取得 43 LINE Developersの各チャネル画面のMessaging APIの下の方にあります

  44. 実装(Handlerを1つ増やす) 44 ※緑塗りが追加部分 localhost:8080/callbackにアクセスしたら lineHandler関数が実行されるうように 実装します

  45. 実装(lineHandler関数) 45 LINEBOT SDKのexampleをほぼそのままコピペです 少しごちゃっとするので、雰囲気をつかむだけでOKです (自分も最初は雰囲気だけでやってました) • LINEBOT SDK •

    https://github.com/line/line-bot-sdk-go • 参考にしたexampleファイル • https://github.com/line/line-bot-sdk- go/blob/master/examples/echo_bot/server.go
  46. 実装(lineHandler関数 前半) 46 LINEBOT初期化 • 28-31行目参照 • linebotパッケージを使うとLINEBOTで 色々できる •

    29, 30行目ではLINE Developersで取得した 認証情報※を記述 ※ 認証情報を載せたままGitHubでソースコード を公開しないように注意 通常は環境変数から取得したりします
  47. 実装(lineHandler関数 前半) 47 変数宣言(複数) • 28行目参照 • Goでは複数の変数(ここではbotとerr)を 宣言できる •

    同様に、関数も複数の値を返せる if文 • 32行目参照 • 条件文に()はいらない
  48. 実装(lineHandler関数 後半) 48 おおまかな処理の流れ • 37-45行目 • リクエストの内容チェック • 46-60行目

    • どのようなイベント※が起こったかを 確認して個別に処理する • 具体的な内容は次スライド ※イベント メッセージ受信、 ポストバック受信など
  49. 実装(lineHandler関数 後半) 49 拡張for文 • 46行目参照 switch文 • 49行目参照

  50. 実装(lineHandler関数 後半) 50 51行目 • 受信したメッセージがテキスト形式の場合 52行目 • 受信したメッセージを取得 53行目

    • メッセージを送信
  51. 【再掲】Messaging APIの仕組み(公式から引用) 1. ユーザーが、LINE公式アカウントにメッセージを送信します。 2. LINEプラットフォームからボットサーバーのWebhook URLに、 Webhookイベントが送信されます。 3. Webhookイベントに応じて、ボットサーバーからユーザーに

    LINEプラットフォームを介して応答します。 51
  52. 実行 52 • ngrokというサービスを使い、外部からローカル環境へのアクセスを可能にする • ngrokが発行するURLをLINE DevelopersのWebhook URLに登録する • BOTを自分のLINEアプリに友だち追加して、メッセージを送信する

    【参考】ngrokの利用方法 https://qiita.com/hirokisoccer/items/7033c1bb9c85bf6789bd
  53. 実行(ローカル環境を外部公開) 53 以下のコマンドを実行する # 8080番を公開したい時は以下の通り $ ngrok http 8080 ngrok

    by @inconshreveable Session Status online Session Expires 7 hours, 59 minutes Version 2.3.35 Region United States (us) Web Interface http://127.0.0.1:4040 Forwarding http://xxxxxx.ngrok.io -> http://localhost:8080 Forwarding https:// xxxxxx.ngrok.io -> http://localhost:8080 httpsのアドレスを Webhookに登録する
  54. 実行(Webhook登録) 54 LINE Developersの各チャネル画面のMessaging APIの下の方にあります

  55. 実行(友だち追加して会話) 55 LINE Developersの各チャネル画面の Messaging APIにQRコードがあるので、 友だち追加して試す

  56. 【再掲】できあがり 56 送信した内容をそのままオウム返しする LINE BOTを作成します

  57. 3.位置情報から 緯度/経度を返すLINEBOT 57

  58. できあがり 58 位置情報を送ったら その位置の緯度と経度を返すよう実装します

  59. 差分 59 https://github.com/yagi-eng/go-linebot-start/compare/parrot...latlng

  60. 実装 60 59-60行目 • 送信されたメッセージが位置情報であれば、 sendRestoInfo関数を実行 • sendRestoInfo関数の実装は次スライド ※このステップでは位置情報を返すだけです が、次ステップでレストラン情報を返すよう

    にするので、関数名にはレストランを入れ ちゃってます
  61. 実装(sendRestoInfo関数) 61 68行目 • イベントから位置情報メッセージを取得 70-71行目 • 緯度と経度を取得 • float型で取得されるので、

    strconv.FormatFloatで文字列に置換
  62. 実装(sendRestoInfo関数) 62 73行目 • 返信するメッセージを生成 • “”中の1つ目に%sにlatが、2つ目の%sにlng が代入される 75行目 •

    メッセージを送信
  63. 【再掲】できあがり 63 位置情報を送ったら その位置の経度と緯度を返すよう実装します

  64. 4.位置情報から 周辺の飲食店を返すLINEBOT 64

  65. できあがり 65 位置情報を送ったら、その周辺の レストラン一覧を返すよう実装します

  66. 差分 66 https://github.com/yagi-eng/go-linebot-start/compare/latlng...resto

  67. ホットペッパーAPI 67 飲食店検索などいろいろできて、かつ気軽に使えるAPI ホットペッパーAPIリファレンス https://webservice.recruit.co.jp/doc/hotpepper/reference.html

  68. APIKEYを発行 68 公式サイトの新規登録より流れで登録できます メアド登録だけなので簡単に使える!

  69. 使用するAPIのレスポンス例 69 https://webservice.recruit.co.jp/hotpepper/gourmet/v1/?key=(YOURKEY)&format =json&large_area=Z011

  70. 実装 70 ※赤塗りが削除部分 75行目 • getRestoInfo関数を作成して、それでメッ セージ返すように変更

  71. 実装(構造体の定義) 71 構造体 • 84, 89, 94行目参照 • 型の異なるデータ型を集めたデータ型 •

    type (構造体の名前) struct{} で定義できる JSONパース • Goでは構造体とJSONの構造を紐づけて パースするのが一般的 • その際は、フィールドの先頭は大文字で 始める必要あり • フィールドの右に`json:”xxx”`と記述する 必要あり
  72. 実装(構造体の定義) 72 見切れてた

  73. 実装(getRestoInfo関数 前半) 73 関数宣言(返り値あり) • 99行目参照 • 引数の後に返り値の型を定義

  74. 実装(getRestoInfo関数 前半) 74 100-104行目 • 実行するAPIのURL生成 107-120行目 • APIを実行し、レスポンスのJSONを Goで扱える形にして117行目の

    response型のdataに格納 • おまじない程度に思ってOK
  75. 実装(getRestoInfo関数 後半) 75 122-126行目 • dataに格納したJSONのデータのうち、お店 の名前と住所を抽出してinfoに格納してい き、それを呼び出し元に返却

  76. 【再掲】できあがり 76 位置情報を送ったら、その周辺の レストラン一覧を返すよう実装します

  77. 5.位置情報から周辺の飲食店を 見やすく返すLINEBOT 77

  78. できあがり 78 位置情報を送ったら、 その周辺のレストラン一覧を 見やすく返すよう実装します この表示形式をカルーセルと言います

  79. 差分 79 https://github.com/yagi-eng/go-linebot-start/compare/resto...carousel

  80. 実装(メッセージ形式を変更) 80 83行目 • bot.ReplyMessage()の第2引数を変更 • before: linebot.NewTextMessage() • after:

    linebot.NewTemplateMessage() split形式の方が diff見やすかったので
  81. 実装(構造体の定義) 81 カルーセル表示用に以下の要素をJSONパース の際に取得するように構造体を定義 • 写真のURL • ホットペッパーのURL

  82. 実装(getRestoInfo関数) 82 スライス宣言 • 143行目参照 • ここでは*linebot.CarouselColumn型の スライスを生成 スライス追加 •

    156行目参照 これ
  83. 実装(getRestoInfo関数) 83 145-148行目 • 住所を定義 • 60字以内に収める必要があるので、 61文字以上ある場合はそれ以降をカット ※runeでは絵文字などは1文字分以上としてカ ウントされます

  84. 実装(getRestoInfo関数) 84 150-155行目 • 1つ1つのカルーセルの実装と実体は以下の ように対応

  85. 【再掲】できあがり 85 位置情報を送ったら、 その周辺のレストラン一覧を 見やすく返すよう実装します この表示形式をカルーセルと言います

  86. 86 以上です!

  87. おまけ 87

  88. 私のGoの独学の進め方 88 https://twitter.com/yagi_eng/status/1277551601167679490

  89. 各種アカウント ・Twitter https://twitter.com/yagi_eng ・Qiita https://qiita.com/yagi_eng ・Wantedly https://www.wantedly.com/users/135658076 ・Instagram https://www.instagram.com/yaginu_travels_around/ https://www.instagram.com/yaginu_nakame_lunch/

    だいだい yagi_eng の アカウント名でやってます 89
  90. とりあえず手元で動かしたい方向け 90 • 以下のリポジトリをclone(またはfolk) • https://github.com/yagi-eng/go-linebot-start/tree/master • LINE DevelopersとホットペッパーAPIに登録して、 BOT作成&各種キーなどを発行

    • ngrok(外部へローカルホストを公開するツール)をインストール • cloneしたmain.goに発行した各種キーを埋め込む • 33, 34, 122行目 • 以下の順にコマンドを実行 • $ ngrok http 8080 #ngrok実行 • $ cd go-linebot-start/answer • $ go run main.go #Go実行 • ngrokが生成したURLをLINE DevelopersのBOTページでWebhookURLに登録 • 作成したボットに位置情報を送信してみる
  91. 91 以下再掲

  92. リポジトリはこちら https://github.com/yagi-eng/go-linebot-start ⇒以下のステップ毎にブランチを作成しています、インデント下がりがブランチ名 • まずはHello, World! • hello-world • オウム返しのLINEBOT

    • parrot • 位置情報から経度/緯度を返すLINEBOT • latlng • 位置情報から周辺の飲食店を返すLINEBOT • resto • 位置情報から周辺の飲食店を見やすく返すLINEBOT • carousel 92
  93. LINE Developersに登録 93 公式サイトを参考にアカウントを作成する ・Messaging APIを始めよう ⇒LINE Developersコンソールでチャネルを作成する https://developers.line.biz/ja/docs/messaging-api/getting-started/ ・ボットを作成する

    ⇒LINE Developersコンソールでボットを設定する https://developers.line.biz/ja/docs/messaging-api/building-bot/
  94. LINE Developersでシークレットを取得 94 LINE Developersの各チャネル画面のBasic settingsの下の方にあります

  95. LINE Developersでアクセストークンを取得 95 LINE Developersの各チャネル画面のMessaging APIの下の方にあります

  96. ホットペッパーAPI 96 飲食店検索などいろいろできて、かつ気軽に使えるAPI ホットペッパーAPIリファレンス https://webservice.recruit.co.jp/doc/hotpepper/reference.html

  97. APIKEYを発行 97 公式サイトの新規登録より流れで登録できます メアド登録だけなので簡単に使える!

  98. 実行 98 • ngrokというサービスを使い、外部からローカル環境へのアクセスを可能にする • ngrokが発行するURLをLINE DevelopersのWebhookに登録する • BOTを自分のLINEアプリに友だち追加して、メッセージを送信する 【参考】ngrokの利用方法

    https://qiita.com/hirokisoccer/items/7033c1bb9c85bf6789bd
  99. 【再掲】Messaging APIの仕組み(公式から引用) 1. ユーザーが、LINE公式アカウントにメッセージを送信します。 2. LINEプラットフォームからボットサーバーのWebhook URLに、 Webhookイベントが送信されます。 3. Webhookイベントに応じて、ボットサーバーからユーザーに

    LINEプラットフォームを介して応答します。 99
  100. 実行(ローカル環境を外部公開) 100 以下のコマンドを実行する # 8080番を公開したい時は以下の通り $ ngrok http 8080 ngrok

    by @inconshreveable Session Status online Session Expires 7 hours, 59 minutes Version 2.3.35 Region United States (us) Web Interface http://127.0.0.1:4040 Forwarding http://xxxxxx.ngrok.io -> http://localhost:8080 Forwarding https:// xxxxxx.ngrok.io -> http://localhost:8080 このアドレスを Webhookに登録する ※httpsであることに注意
  101. 実行(Webhook登録) 101 LINE Developersの各チャネル画面のMessaging APIの下の方にあります

  102. 実行(友だち追加して会話) 102 LINE Developersの各チャネル画面の Messaging APIにQRコードがあるので、 友だち追加して試す