Go言語(golang)でS3からファイルを取得する

データアナリティクス事業本部の森脇です。

最近業務でよくGo言語を使用します。 今回はaws-sdk-goを使って、S3からファイルを取得する方法についてご紹介したいと思います。

使用するGo言語のバージョンは1.13.6です。

aws-sdk-goをインストールする

go getコマンドを使ってインストールします。

$ go get -u github.com/aws/aws-sdk-go
.
.
$ cat go.mod
module example.com/moriwaki/s3read

go 1.13

require github.com/aws/aws-sdk-go v1.28.6 // indirect

v1.28.6がインストールされました。

作っていく

main.goというファイルを作成し、実装していきます。

AWSのクレデンシャルは、aws-cliなどを使って事前に設定しておきます。

sessionを作成する

S3に接続する際に、まずはsessionを作成します。

package main

import (
	"github.com/aws/aws-sdk-go/aws/session"
)

func main() {
	// sessionの作成
	sess := session.Must(session.NewSessionWithOptions(session.Options{
		SharedConfigState: session.SharedConfigEnable,
	}))
}

オプションの「SharedConfigState」に「SharedConfigEnable」を設定することで、~/.aws/config内を参照してくれるようになります。

クレデンシャルをprofile名で指定したい場合は、オプションの「Profile」を使います。

	// sessionの作成
	sess := session.Must(session.NewSessionWithOptions(session.Options{
		Profile: "profileName",
		SharedConfigState: session.SharedConfigEnable,
	}))
}

S3からファイルをダウンロードする

s3managerのDownloaderを使用します。

package main

import (
	"log"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
)

func main() {
	// sessionの作成
	sess := session.Must(session.NewSessionWithOptions(session.Options{
		Profile:           "di",
		SharedConfigState: session.SharedConfigEnable,
	}))

	// S3オブジェクトを書き込むファイルの作成
	f, err := os.Create("sample.txt")
	if err != nil {
		log.Fatal(err)
	}

	bucketName := "xxx-bucket"
	objectKey := "xxx-key"

	// Downloaderを作成し、S3オブジェクトをダウンロード
	downloader := s3manager.NewDownloader(sess)
	n, err := downloader.Download(f, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
	})
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("DownloadedSize: %d byte", n)
}

downloader.Dowload()関数は、ダウンロードしたサイズを第1戻り値として返します。

実行してみます。

$ go run main.go
2020/01/21 18:05:32 DownloadedSize: 20 byte

成功し、ダウンロードしたオブジェクトのサイズを取得できました。

ダウンロードせずに読み込む

先程の例ではファイル化してダウンロードまで行いましたが、今度はファイルとして 落とさずに読み込みを行います。

package main

import (
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
)

func main() {
	// sessionの作成
	sess := session.Must(session.NewSessionWithOptions(session.Options{
		Profile:           "di",
		SharedConfigState: session.SharedConfigEnable,
	}))

	bucketName := "xxx-bucket"
	objectKey := "xxx-key"

	// S3 clientを作成
	svc := s3.New(sess)

	obj, err := svc.GetObject(&s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
	})
	if err != nil {
		log.Fatal(err)
	}

	// 最初の10byteだけ読み込んで表示
	rc := obj.Body
	defer rc.Close()
	buf := make([]byte, 10)
	_, err = rc.Read(buf)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("%s", buf)
}

実行してみます。

$ go run main.go
2020/01/21 18:10:15 Hello! Go.

読み込みに成功し、ストレージを利用することなくファイルを読み込むことができました。

GetObject()の戻り値のBodyの型は「io.ReadCloser」インターフェースですので

各種ライブラリとお手軽に連携できそうです。

まとめ

aws-sdk-goを使うことで、簡単にS3のファイルを読み込むことができました。

次回はS3にファイルをアップロードする部分を実践したいと思います。

参考サイト