Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
🐭 Lambda関数をGoで実装してみた話
Search
⛵️ 長谷川 広樹 🐬
March 26, 2021
Programming
0
920
🐭 Lambda関数をGoで実装してみた話
社内LTにて、Goを布教しようと試みましたʕ◔ϖ◔ʔ
⛵️ 長谷川 広樹 🐬
March 26, 2021
Tweet
Share
More Decks by ⛵️ 長谷川 広樹 🐬
See All by ⛵️ 長谷川 広樹 🐬
♾️ マルチプロダクトの巨大組織でマイクロサービス開発を支えるCICDプラットフォーム設計
hiroki_hasegawa
5
4k
🐙 KubernetesのマルチテナントパターンとArgoCDの実践テナント設計
hiroki_hasegawa
4
3.4k
🧑🚀 tfstate の分割パターンとディレクトリ構成への適用
hiroki_hasegawa
8
7.7k
⛵️ Istioのサービス間通信を実現するサービスディスカバリーの仕組み
hiroki_hasegawa
3
7.2k
🔍 可観測性に入門しよう
hiroki_hasegawa
1
1.1k
🏗️ ドメイン駆動設計と依存性逆転の原則
hiroki_hasegawa
14
10k
🤝🏻 依存関係と依存オブジェクト注入
hiroki_hasegawa
2
1.3k
🐭 Goに入門しよう
hiroki_hasegawa
0
730
♾️ SREに入門しよう
hiroki_hasegawa
1
850
Other Decks in Programming
See All in Programming
Microservices rules: What good looks like
cer
PRO
0
460
Level up your Gemini CLI - D&D Style!
palladius
1
160
Querying Design System デザインシステムの意思決定を支える構造検索
ikumatadokoro
1
1.2k
複数人でのCLI/Infrastructure as Codeの暮らしを良くする
shmokmt
5
2.1k
非同期処理の迷宮を抜ける: 初学者がつまづく構造的な原因
pd1xx
1
420
GeistFabrik and AI-augmented software development
adewale
PRO
0
240
手が足りない!兼業データエンジニアに必要だったアーキテクチャと立ち回り
zinkosuke
0
350
JJUG CCC 2025 Fall: Virtual Thread Deep Dive
ternbusty
3
510
dnx で実行できるコマンド、作ってみました
tomohisa
0
130
俺流レスポンシブコーディング 2025
tak_dcxi
13
7.5k
なあ兄弟、 余白の意味を考えてから UI実装してくれ!
ktcryomm
10
11k
【CA.ai #3】Google ADKを活用したAI Agent開発と運用知見
harappa80
0
240
Featured
See All Featured
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
960
How GitHub (no longer) Works
holman
316
140k
Six Lessons from altMBA
skipperchong
29
4.1k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
1.8k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
700
A Modern Web Designer's Workflow
chriscoyier
697
190k
A Tale of Four Properties
chriscoyier
162
23k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
How To Stay Up To Date on Web Technology
chriscoyier
791
250k
Designing Experiences People Love
moore
142
24k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
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.