aws-sdk-goを触ってみた所感
普段はcli, Ruby, Node.jsなどでAWSと戯れていますが、今回初めてaws-sdk-go
を使ってみたので所感をしたためておきます。
▼題材はこれです。
Rubyで書いた40行ほどのスクリプトをGo実装で焼き直してみました。
rezept/main.go at master · Blue-Pix/rezept · GitHub
ちなみにGoは本当にちょっとしか書いたことがないです。
文法は一通りさらってありますが、細かい作法はよく知りません。
なのでaws-sdk-goではなくGoそのものに対する所感を含まれているかもしれません。
パッケージ
AWSまわりはこのへん
import( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/cloudformation" )
aws
はポインタを返すaws.String()
や、認証のconfigとかで使う。
レスポンスもaws.StringValue()
とかで扱ってますが、このヘルパーって自分でポインタにすれば別に使わなくてもいいんだよね...?
awserr
はエラーコードの判定。詳細知らなくてもよければ特に必要ない。
session
は認証で、service/cloudformation
は各サービスのAPI実装。
認証
環境変数のアクセスキーやプロファイルを順に読み込んでいくのは他のSDKと変わらず。
特に何も指定しない場合はこう。
sess := session.Must(session.NewSession())
session.Must()
を使えば以下のようなハンドリングを書かずに済む。
sess, err := session.NewSession() if err != nil { panic(err) }
プロファイルを使う場合はこういう感じ。
sess := session.Must(
session.NewSessionWithOptions(
session.Options{
Profile: "myProfile",
},
),
)
API
サービスごとにクライアントの作成
service := cloudformation.New(sess)
パラメータは、各APIの名前にInput
というサフィックスをつけた構造体で渡す。ListStacks
APIであれば、ListStacksInput
になる。
params := &cloudformation.ListStacksInput{ NextToken: token, }
実行。
resp, err := service.ListStacks(params) if err != nil { panic(err) }
レスポンスはポインタになるのでaws.StringValue
とかを使って変換する。
for _, stack := range resp.StackSummaries { result[aws.StringValue(stack.StackId)] = aws.StringValue(stack.StackName) }
ページングも同じで次ページのトークンを含める方式。
if resp.NextToken != nil { listStacks(sess, resp.NextToken, result) }
サービス名とAPI名を一定のルールに沿って変換するだけなので特に難しくない。他の言語でAWS実装に親しんでいればなんとなくで予想して書ける。
使えないオプションがある
例えばaws cloudformation list-stacks
にはmax-items
というオプションがあるが、aws-sdk-goの方では使用できない。
list-stacks — AWS CLI 1.18.53 Command Reference
エラーハンドリング
詳細にエラーの種類を把握したい時にはawserr.Error
に変換してごにょごにょやる必要がある。
Handling Errors in the AWS SDK for Go - AWS SDK for Go
このあたりちょっと記述が冗長になってつらい。
resp, err := service.ListImports(params) if err != nil { if aerr, ok := err.(awserr.Error); ok { if aerr.Code() == "ValidationError" && strings.Contains(aerr.Message(), "is not imported by any stack") { return } } panic(err) }
参考資料
その他Goに対する所感
- いまはGo modulesが主流なんですか?
- スライスはポインタであってポインタではない...?
- デフォルト引数サクッと使いたい。Functional Option Pattern...?