Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
🐭 Lambda関数をGoで実装してみた話
Search
⛵️ 長谷川 広樹 🐬
March 26, 2021
Programming
1k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
🐭 Lambda関数をGoで実装してみた話
社内LTにて、Goを布教しようと試みましたʕ◔ϖ◔ʔ
⛵️ 長谷川 広樹 🐬
March 26, 2021
More Decks by ⛵️ 長谷川 広樹 🐬
See All by ⛵️ 長谷川 広樹 🐬
『Kubernetes ☸️ で実践する Platform Engineering 』を最高速度で読み抜いたる!!👊🏻
hiroki_hasegawa
1
280
♾️ マルチプロダクトの巨大組織でマイクロサービス開発を支えるCICDプラットフォーム設計
hiroki_hasegawa
5
5k
🐙 KubernetesのマルチテナントパターンとArgoCDの実践テナント設計
hiroki_hasegawa
4
3.9k
🧑🚀 tfstate の分割パターンとディレクトリ構成への適用
hiroki_hasegawa
8
9k
⛵️ Istioのサービス間通信を実現するサービスディスカバリーの仕組み
hiroki_hasegawa
3
7.7k
🔍 可観測性に入門しよう
hiroki_hasegawa
1
1.2k
🏗️ ドメイン駆動設計と依存性逆転の原則
hiroki_hasegawa
14
11k
🤝🏻 依存関係と依存オブジェクト注入
hiroki_hasegawa
2
1.4k
🐭 Goに入門しよう
hiroki_hasegawa
0
790
Other Decks in Programming
See All in Programming
プロジェクトコードをキレイキレイしよう!暗黙的な参照を読み解く静的解析
ostk0069
0
190
baseline으로 마이그레이션, 리팩토링 안전하게 맡기기
fornewid
1
520
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
240
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
490
Groovy as a human and AI friendly programming language
paulk
0
140
Optunaを作ったときにやりたかったこと、その後 (2026/10/16, Optuna Meetup #3)
iwiwi
4
1.4k
Seven New Principles of Software Engineering
yegor256
0
380
flutter_test のその先へ — Flutter アプリの LLM 機能に「評価」という品質保証を
kosukesaigusa
0
140
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
1.1k
SFCで実現する病院・医療システムの動的組み立て式UI
koukimiura
1
140
Event is what happens
moro
2
2.1k
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
200
Featured
See All Featured
The Cult of Friendly URLs
andyhume
79
7k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
500
A designer walks into a library…
pauljervisheath
211
25k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
290
RailsConf 2023
tenderlove
30
1.6k
A Tale of Four Properties
chriscoyier
163
24k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
Are puppies a ranking factor?
jonoalderson
2
4.1k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.7k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
590
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.