Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
🐭 Lambda関数をGoで実装してみた話
Search
長谷川 ⛵️ 広樹
March 26, 2021
Programming
0
890
🐭 Lambda関数をGoで実装してみた話
社内LTにて、Goを布教しようと試みましたʕ◔ϖ◔ʔ
長谷川 ⛵️ 広樹
March 26, 2021
Tweet
Share
More Decks by 長谷川 ⛵️ 広樹
See All by 長谷川 ⛵️ 広樹
♾️ マルチプロダクトの巨大組織でマイクロサービス開発を支えるCICDプラットフォーム設計
hiroki_hasegawa
4
3.3k
🐙 KubernetesのマルチテナントパターンとArgoCDの実践テナント設計
hiroki_hasegawa
4
3k
🧑🚀 tfstate の分割パターンとディレクトリ構成への適用
hiroki_hasegawa
8
7.1k
⛵️ Istioのサービス間通信を実現するサービスディスカバリーの仕組み
hiroki_hasegawa
3
6.9k
🔍 可観測性に入門しよう
hiroki_hasegawa
1
1.1k
🏗️ ドメイン駆動設計と依存性逆転の原則
hiroki_hasegawa
14
9.6k
🤝🏻 依存関係と依存オブジェクト注入
hiroki_hasegawa
2
1.3k
🐭 Goに入門しよう
hiroki_hasegawa
0
710
♾️ SREに入門しよう
hiroki_hasegawa
1
830
Other Decks in Programming
See All in Programming
Deep Dive into ~/.claude/projects
hiragram
14
2.5k
VS Code Update for GitHub Copilot
74th
2
640
「テストは愚直&&網羅的に書くほどよい」という誤解 / Test Smarter, Not Harder
munetoshi
0
170
明示と暗黙 ー PHPとGoの インターフェイスの違いを知る
shimabox
2
510
おやつのお供はお決まりですか?@WWDC25 Recap -Japan-\(region).swift
shingangan
0
140
「Cursor/Devin全社導入の理想と現実」のその後
saitoryc
0
820
すべてのコンテキストを、 ユーザー価値に変える
applism118
3
1.3k
ペアプロ × 生成AI 現場での実践と課題について / generative-ai-in-pair-programming
codmoninc
1
18k
AIともっと楽するE2Eテスト
myohei
6
2.6k
AIと”コードの評価関数”を共有する / Share the "code evaluation function" with AI
euglena1215
1
160
PipeCDのプラグイン化で目指すところ
warashi
1
270
今ならAmazon ECSのサービス間通信をどう選ぶか / Selection of ECS Interservice Communication 2025
tkikuc
21
4k
Featured
See All Featured
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Rails Girls Zürich Keynote
gr2m
95
14k
Fireside Chat
paigeccino
37
3.5k
Music & Morning Musume
bryan
46
6.6k
Become a Pro
speakerdeck
PRO
29
5.4k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
Speed Design
sergeychernyshev
32
1k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
181
54k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.5k
Adopting Sorbet at Scale
ufuk
77
9.5k
Being A Developer After 40
akosma
90
590k
Transcript
Lambda関数を Goで実装してみた話 株式会社ユニクエスト 長谷川広樹 github.com/hiroki-it @Hiroki__IT
自己紹介 ▼ お仕事 最近:クラウドインフラ、IaC、CICD、... 以前:DDD ▼ 関心のある技術領域 ・クラウドインフラ ・IaC ・DDD
github.com/hiroki-it @Hiroki__IT 長谷川 広樹 (はせがわ ひろき) 株式会社ユニクエスト
目次 ▪ Goの概要 ▪ ディレクトリ構造 ▪ Goの基本文法 ▪ Goファイルの要素 ▪
Lambdaを使用した通知処理
Goの概要(1) 手続き型言語のため,オブジェクト機能なし. 第9回 UMTPモデリング技術 ワークショップ https://umtp-japan.org/
Goの概要(2) 静的型付け言語のため,ソースの実行前にビルドが必要. ビルドの成果物 = アーティファクト https://www.atmarkit.co.jp/ait/articles/1105/23/news128.html
Goの概要(3) 実装方法が強制されるため,可読性が高く,後続者が開発がしやすい 実装がスケーリングしやすい 静的解析のルールが厳しいため,バグを事前に見つけられる バグが許されない基盤部分に適している
ディレクトリ構造(1) ・bin ビルドされたアーティファクト(バイナリファイル)を配置. ・pkg アーティファクトとは別に生成されるファイルを配置. ・src ソースコードを配置. $GOPATH # 決まりは無いが,$HOME/go
とすることが多い ├── bin ├── pkg └── src
ディレクトリ構造(2) notify-slack-of-amplify-events # srcに相当 │ ├── build │ └── Dockerfile ├──
cmd │ ├── main.go │ ├── controllers │ ├── entities │ └── usecases │ ├── config ├── test ├── .air.toml ├── docker-compose.yml ├── go.mod └── go.sum https://github.com/hiroki-it/notify-slack-of-amplify-events ディレクトリ構造ベストプラクティス:https://github.com/golang-standards/project-layout
ディレクトリ構造(3) ・build Dockerfileを配置. ・cmd main.goファイルや,サブmainパッケージを配置. src # ソースコードを配置 ├── build
└── cmd ├── main.go ├── controllers ├── entities └── usecases
Goファイルの要素(1) package <パッケージ名> // 名前空間の宣言 import "<パッケージ名>" // パッケージの読み込み func
Xxx(){ // 関数 } ・一つのディレクトリ内では一つのパッケージ名のみ. ・関数名は,頭文字が大文字だとパブリック,小文字だとプライベートになる.
Goファイルの要素(2) package main func main(){ } ・エントリポイントは,cmdディレクトリまたはその子ディレクトリに配置. ・パッケージ名はmain. ・関数名はmain.
Goファイルの要素(3) func Division(x int, y int) (int, int) { //
商を計算する. quotient := x / y // 余りを計算する. remainder := x % y // 商と余りを返却する. return quotient, remainder } ・引数と返却値の型に厳格. ・複数の値を返却可能.
Goの環境構築(1) FROM golang:1.15 ENV CGO_ENABLED=0 # C言語製のライブラリの有効化 ENV GOOS=linux #
Goが稼働するOS(※GoはOSに縛られない) ENV GOARCH=amd64 # CPUアーキテクチャ ENV GO111MODULE=on # go.modの有効化 WORKDIR ${GOPATH}/src 最近,『go.mod(≒ composer.json)』『go.sum(≒ composer.lock)』が導入
Goの環境構築(2) module github.com/hiroki-it/notify-slack-of-amplify-events go 1.15 require ( # プロトコルを除いたURLとバージョンでパッケージを必ず指定 github.com/aws/aws-lambda-go
v1.23.0 github.com/stretchr/testify v1.7.0 ) replace ( # mainパッケージの共通部品も,インターネット上に存在することを強制 github.com/hiroki-it/notify-slack-of-amplify-events/cmd/entities/xxx => /cmd/entities/xxx ) あらゆるパッケージはインターネット上にリリースされるべきという思想 go.modファイル
Goの環境構築(3) # インストールのキャッシュを活用するためにコピーしておく. COPY go.mod go.sum ./ # パッケージをインストールする. RUN
go get -u github.com/cosmtrek/air \ && go mod download -x COPY . . ・mod downloadコマンド go.modファイルに実装したパッケージをインストール
Goの環境構築(4) https://github.com/cosmtrek/air ソースコード変更の度にビルドを行うホットリロードツール『Air』
Goの環境構築(5) # ビルドのアーティファクトを/go/binに配置する. RUN go build -x -o go/bin ./cmd
CMD ["/go/bin/cmd"] ・cmdディレクトリ ベストプラクティスに則り,cmdディレクトリにソースコードを配置. ・buildコマンド ソースコードをビルドし,binディレクトリにアーティファクトを配置.
Lambdaを使用した通知処理(1) package main import ( "github.com/aws/aws-lambda-go/lambda" "github.com/hiroki-it/notify-slack-of-amplify-events/cmd/controllers/handler" ) // lambdaパッケージからStartメソッドをコール
func main() { lambda.Start(handler.HandleRequest) // slackパッケージのHandler関数をコール } main.goファイル
Lambdaを使用した通知処理(2) func HandleRequest(request Request) error { var event eventbridge.Event //
EventBridgeから転送されたJSONを受信し,構造体にマッピングします. err := json.Unmarshal([]byte(request.Records[0].EventBridge.Event), &event) slackClient := slack.NewSlackClient() message := slackClient.BuildMessage(event) return slackClient.PostMessage(message) } 構造体?? 構造体とJSONのマッピング?? handler.goファイル
Lambdaを使用した通知処理(3) type Person struct { Name string // 構造体が持つデータの型 }
func main() { person := Person{"Hiroki"} // 構造体にデータを設定する. fmt.Printf("%#v\n", person.Name) // "Hiroki" } ・構造体とは,メソッドは持たず,データのみを持つもの. ・関数に構造体を関連付けることで,オブジェクトを擬似的に表現可能.
Lambdaを使用した通知処理(4) type Person struct { // 構造体 Name string }
func (person Person) SetName(name string) { // セッター関数を構造体に関連付ける person.Name = name } func (person Person) GetName() string { // ゲッター関数を構造体に関連付ける return person.Name } func main() { person := Person{Name: "Gopher"} person.SetName("Hiroki") // セッター関数で値を上書きする fmt.Printf("%#v\n", person.GetName()) // "Gopher" }
Lambdaを使用した通知処理(5) type Event struct { Version string `json:"version"` ... Detail
struct { AppId string `json:"appId"` BranchName string `json:"branchName"` JobId string `json:"jobId"` JobStatus string `json:"jobStatus"` } `json:"detail"` } JSONと構造体で相互変換するため,構造体の定義時にJSONマッピングが必要 { "event": { "version": "0", ... "detail": { "appId": "dd31ugx1agx51", "branchName": "feature/293_deploy_to_amplify", "jobId": "2", "jobStatus": "SUCCEED" } } }
Lambdaを使用した通知処理(6) func Handler(request Request) error { var event eventbridge.Event err
:= json.Unmarshal([]byte(request.Records[0].EventBridge.Event), &event) slackClient := slack.NewSlackClient() // 通知メッセージのJSONを構成します. message := slackClient.BuildMessage(event) return slackClient.PostMessage(message) } https://github.com/hiroki-it/notify-slack-of-amplify-events/blob/develop/cmd/ buildMessageメソッドで構成される構造体は,slackのtype.goの閲覧を推奨
Lambdaを使用した通知処理(7) func postMessage(message Message) error { json, err := json.Marshal(message)
// マッピングを元に,構造体をJSONに変換する. request, err := http.NewRequest( // リクエストメッセージを定義する. "POST", os.Getenv("SLACK_API_URL"), bytes.NewBuffer(json), ) ... ・JSONをMessage構造体にマッピング. ・POSTリクエストの必要なパラメータを設定. post.goファイル
Lambdaを使用した通知処理(8) … request.Header.Set("Content-Type", "application/json") // ヘッダーを定義する. request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", os.Getenv("SLACK_API_TOKEN")))
client := &http.Client{} response, err := client.Do(request) // HTTPリクエストを送信する. defer response.Body.Close() // deferで宣言しておき,HTTP通信を必ず終了できるようにする. return nil } ・クライアントを起動し,リクエストを送信. ・defer宣言された関数は,たとえ処理が停止しても最後に必ず実行される.
おまけ:例外処理 json, err := json.Marshal(...) if err != nil {
return err } request, err := http.NewRequest(...) if err != nil { return err } ・Goの思想では例外処理は無駄なものとされ,try-catchが無い. ・多くの関数は二つ目の返却値にエラーを返すため,毎回検証するしかない.
最後に Gopherくん 超かわいい!!! by Takuya Ueda (https://twitter.com/tenntenn) The Gopher character
is based on the Go mascot designed by Renée French.