Let's Get Started with Echo, Go, AWS SDK for GO, and AWS S3
Tags: aws, go, tutorial, programming
Published: 2022-03-25 12:30:00

## Preparation

We need to prepare some tools, such as:

1. Go. You may download it [here](https://go.dev/dl/). In this post, I use Go 1.18.
2. Your Favorite IDE (Integrated Development Environment).
3. Postman. You may download [here](https://www.postman.com/). Feel free to use other similar tools.

## Setup AWS S3 and IAM User

* Open AWS Console
* Search S3 in the search bar. Click the S3.

![Search S3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uv5eahk1xveh231b48x2.png)

* Click `Create bucket`

![Create Bucket Menu](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owgsop75ec33p1e779hs.png)

* Fill in the bucket name and select AWS region. After that, click `Create bucket`.

Note: We let the config as it is. You may configure it.

![Create bucket form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/07qk3fzfzoyb21kfaq2q.png)
 
* Go to IAM -> Users.

* Create a new user. We will create a user that will have a responsibility to upload the files. Click `Add User`.

![New User](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efrlc7enqsy7s3rijun6.png)

* Fill in the user name and tick the `Access key - Programmatic access`

![Add User Form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xim0y8eiwxtl2cp4esro.png)
 
* Click `Next`. We will setup the permission. For now, we will use `AmazonS3FullAccess`. You may setup custom permissions to achieve the least privilege.

![S3 Permission](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/773v6eapi2k3lgusyamb.png)

* You may configure other settings and create a user.

* After that, copy and save the credentials. You will use this later.

![Credentials](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ccx9fnf8cnqv8pzlzgi.png)
 
## Time to Code

* Prepare a folder/directory for your project.

* Open the terminal (make sure the current directory is your project). Initiate go module. Run `go mod init <project name>`, example: `go mod init explore-go`.

* Add our dependencies. First I add Echo. `go get github.com/labstack/echo/v4`

* Add AWS SDK and S3 service.

```bash
go get github.com/aws/aws-sdk-go-v2
go get github.com/aws/aws-sdk-go-v2/config
go get github.com/aws/aws-sdk-go-v2/service/s3
go get github.com/aws/aws-sdk-go-v2/feature/s3/manager
```

* Create file `server.go` with code below. Don't forget to change the bucket name.

```go
package main

import (
	"context"
	"mime/multipart"
	"net/http"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

type UploadResult struct {
	Path string `json:"path" xml:"path"`
}

func upload(c echo.Context) error {
	file, err := c.FormFile("file")
	if err != nil {
		return err
	}
	src, err := file.Open()
	if err != nil {
		return err
	}
	defer src.Close()
	result, err := UploadToS3(c, file.Filename, src)
	if err != nil {
		return err
	}
	data := &UploadResult{
		Path: result,
	}
	return c.JSON(http.StatusOK, data)
}

func UploadToS3(c echo.Context, filename string, src multipart.File) (string, error) {
	logger := c.Logger()
	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		logger.Fatal(err)
		return "", err
	}
	client := s3.NewFromConfig(cfg)
	uploader := manager.NewUploader(client)
	result, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{
		Bucket: aws.String("<change this with your bucket name>"),
		Key:    aws.String(filename),
		Body:   src,
	})
	if err != nil {
		logger.Fatal(err)
		return "", err
	}
	return result.Location, nil
}

func main() {
	e := echo.New()
	e.Use(middleware.Logger())
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.POST("/upload", upload)

	e.Logger.Fatal(e.Start(":1323"))
}
```

* Setup environment variable.

(For Linux)
```bash
export AWS_REGION=<change with your region>
export AWS_ACCESS_KEY_ID=<change with your key id>
export AWS_SECRET_ACCESS_KEY=<change with you access key>
```

You can use any name but I recommend the name of the file `.env.sh`. After that run the file using `source .env.sh`.

(For Windows)
```powershell
set AWS_REGION=<change with your region>
set AWS_ACCESS_KEY_ID=<change with your key id>
set AWS_SECRET_ACCESS_KEY=<change with you access key>
```

You can use any name but I recommend the name of the file `env.bat`. After that run the file using `env.bat`.

* Run our server. `go run server.go`.

![Server Running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ayfrw7bjw11cwojyi2a8.png)

* Call our API with Postman. Make sure you fill correct address bar, HTTP method, and body. After that click Send.

![API Call](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxpynhos1zrx2uqprme8.png)

* If successful, you will get a message like this in the console.

![Success](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qiujm31nurwcubrz8hnb.png)
 
* Open S3. Make sure your file is in there.

![Bucket Result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ice8r7yurtyyjyle0gls.png)

## Github Project

{% github berviantoleo/explore-go %}

## Awesome

You are awesome!

![Awesome GIF](https://media.giphy.com/media/vCKC987OpQAco/giphy.gif)

<figcaption>GIF Image Source: https://i.giphy.com/media/vCKC987OpQAco/giphy.gif</figcaption>
 
If you have any questions or problems, feel free to ask for help.

Thank you.