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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
⛵️ 長谷川 広樹 🐬
March 26, 2021
Programming
970
0
Share
🐭 Lambda関数をGoで実装してみた話
社内LTにて、Goを布教しようと試みましたʕ◔ϖ◔ʔ
⛵️ 長谷川 広樹 🐬
March 26, 2021
More Decks by ⛵️ 長谷川 広樹 🐬
See All by ⛵️ 長谷川 広樹 🐬
『Kubernetes ☸️ で実践する Platform Engineering 』を最高速度で読み抜いたる!!👊🏻
hiroki_hasegawa
1
160
♾️ マルチプロダクトの巨大組織でマイクロサービス開発を支えるCICDプラットフォーム設計
hiroki_hasegawa
5
4.5k
🐙 KubernetesのマルチテナントパターンとArgoCDの実践テナント設計
hiroki_hasegawa
4
3.7k
🧑🚀 tfstate の分割パターンとディレクトリ構成への適用
hiroki_hasegawa
8
8.3k
⛵️ Istioのサービス間通信を実現するサービスディスカバリーの仕組み
hiroki_hasegawa
3
7.5k
🔍 可観測性に入門しよう
hiroki_hasegawa
1
1.2k
🏗️ ドメイン駆動設計と依存性逆転の原則
hiroki_hasegawa
14
10k
🤝🏻 依存関係と依存オブジェクト注入
hiroki_hasegawa
2
1.4k
🐭 Goに入門しよう
hiroki_hasegawa
0
760
Other Decks in Programming
See All in Programming
Liberating Ruby's Parser from Lexer Hacks
ydah
2
2.7k
20260514 - build with ai 2026 - build LINE Bot with Gemini CLI
line_developers_tw
PRO
0
440
mruby on C#: From VM Implementation to Game Scripting (RubyKaigi 2026)
hadashia
2
1.8k
[RubyKaigi 2026] Require Hooks
palkan
1
320
なぜあなたのコードには「コシ」がないのか?〜AI時代に問う、最後まで美味しい設計と戦略〜 #phpconkagawa / phpconkagawa2026
shogogg
0
200
AIと共に生きる技術選定 2026
sgash708
0
140
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
440
AIを導入する前にやるべきこと
negima
2
360
My daily life on Ruby
a_matsuda
3
380
書籍「ユーザーストーリーマッピング」が私のバイブル
asumikam
4
490
Kubernetesを使わない環境にもCloud Nativeなデプロイを実現する / Enabling Cloud Native deployments without the complexity of Kubernetes
linyows
3
400
SkillsをS3 Filesに置く時のあれこれ
watany
3
1.6k
Featured
See All Featured
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
240
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
190
How to Ace a Technical Interview
jacobian
281
24k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
390
Un-Boring Meetings
codingconduct
0
290
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.2k
Testing 201, or: Great Expectations
jmmastey
46
8.1k
It's Worth the Effort
3n
188
29k
Faster Mobile Websites
deanohume
310
31k
Docker and Python
trallard
47
3.8k
Designing Powerful Visuals for Engaging Learning
tmiket
1
360
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.9k
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.