Athena aws-sdk-go-v2で結果を取得するAthena のAPIを使って結果を取得することができるが、 サイズが大きいときにページネーションを考慮したりメモリを使用するので、S3 からリザルトCSVをダウンロードして、1行ずつ読み込むようにする。

import (
	"context"
	"fmt"
	"log"
	"log/slog"
	"os"
 
	"github.com/aws/aws-sdk-go-v2/aws"
	s3manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
	"github.com/aws/aws-sdk-go-v2/service/s3"
)
 
const s3Bucket = "aws-athena-query-results-my-bucket"
const s3Key = "my_prefix"
const resultFile = "result.csv"
 
type s3Client interface {
	GetObject(context.Context, *s3.GetObjectInput, ...func(*s3.Options)) (*s3.GetObjectOutput, error)
}
 
func DownloadQueryResult(ctx context.Context, s3Client s3Client, queryExecutionId string, outFile string) error {
	file, err := os.Create(outFile)
	if err != nil {
		return err
	}
	defer file.Close()
 
	key := fmt.Sprintf("%s/%s.csv", s3Key, queryExecutionId)
	downloader := s3manager.NewDownloader(s3Client)
	bytes, err := downloader.Download(ctx, file, &s3.GetObjectInput{
		Bucket: aws.String(s3Bucket),
		Key:    aws.String(key),
	})
 
	if err != nil {
		log.Fatal(err)
	}
 
	slog.Info("Downloaded", "file", resultFile, "size(MB)", bytes/1000/1000)
	return nil
}

この関数に、AthenaのqueryExecutionIdを渡して、ファイルとしてダウンロードする。 ここではファイルにしているが、 s3manager.WriteAtBuffer に変えればbufferに展開される。 io.PipeWriterio.PipeReader を使って繋げてやればstreamにもできそう。