Skip to content

Commit 5032bbc

Browse files
committed
Golang meetup Guadalajara example
0 parents  commit 5032bbc

File tree

16 files changed

+657
-0
lines changed

16 files changed

+657
-0
lines changed

README.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Example of hexagonal architecture. See this article: https://www.joeldholmes.com/post/go-hex-arch/
2+
3+
Run the project.
4+
- Install aws cli
5+
6+
go get
7+
8+
- For database selection
9+
go run main.go --database redis
10+
11+
- For handler selection
12+
go run main.go --handler localhost
13+
14+
15+

adding/drone.go

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package adding
2+
3+
type Drone struct {
4+
ID string `json:"id" db:"id"`
5+
Name string `json:"name" db:"name"`
6+
Description string `json:"description" db:"description"`
7+
}

adding/service.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package adding
2+
3+
import (
4+
"github.com/google/uuid"
5+
)
6+
7+
type DroneRepository interface {
8+
Create(drone *Drone) error
9+
}
10+
11+
type DroneService interface {
12+
CreateDrone(drone *Drone) error
13+
}
14+
15+
type droneService struct {
16+
repo DroneRepository
17+
}
18+
19+
func NewDroneService(repo DroneRepository) DroneService {
20+
return &droneService{
21+
repo,
22+
}
23+
}
24+
25+
func (s *droneService) CreateDrone(drone *Drone) error {
26+
drone.ID = uuid.New().String()
27+
return s.repo.Create(drone)
28+
}

database/dynamodb/adding.go

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package dynamodb
2+
3+
import (
4+
"Project/adding"
5+
"fmt"
6+
7+
"github.com/aws/aws-sdk-go/aws"
8+
"github.com/aws/aws-sdk-go/aws/awserr"
9+
"github.com/aws/aws-sdk-go/aws/session"
10+
"github.com/aws/aws-sdk-go/service/dynamodb"
11+
)
12+
13+
type droneAddingRepository struct {
14+
sess *session.Session
15+
}
16+
17+
func NewDynamoAddingRepository(sess *session.Session) adding.DroneRepository {
18+
return &droneAddingRepository{
19+
sess,
20+
}
21+
}
22+
23+
func (r *droneAddingRepository) Create(drone *adding.Drone) error {
24+
svc := dynamodb.New(r.sess)
25+
input := &dynamodb.PutItemInput{
26+
Item: map[string]*dynamodb.AttributeValue{
27+
"ID": {
28+
S: aws.String(drone.ID),
29+
},
30+
"Name": {
31+
S: aws.String(drone.Name),
32+
},
33+
"Description": {
34+
S: aws.String(drone.Description),
35+
},
36+
},
37+
38+
TableName: aws.String("drones"),
39+
}
40+
41+
_, err := svc.PutItem(input)
42+
if err != nil {
43+
if aerr, ok := err.(awserr.Error); ok {
44+
switch aerr.Code() {
45+
case dynamodb.ErrCodeConditionalCheckFailedException:
46+
fmt.Println(dynamodb.ErrCodeConditionalCheckFailedException, aerr.Error())
47+
case dynamodb.ErrCodeProvisionedThroughputExceededException:
48+
fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error())
49+
case dynamodb.ErrCodeResourceNotFoundException:
50+
fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error())
51+
case dynamodb.ErrCodeItemCollectionSizeLimitExceededException:
52+
fmt.Println(dynamodb.ErrCodeItemCollectionSizeLimitExceededException, aerr.Error())
53+
case dynamodb.ErrCodeTransactionConflictException:
54+
fmt.Println(dynamodb.ErrCodeTransactionConflictException, aerr.Error())
55+
case dynamodb.ErrCodeRequestLimitExceeded:
56+
fmt.Println(dynamodb.ErrCodeRequestLimitExceeded, aerr.Error())
57+
case dynamodb.ErrCodeInternalServerError:
58+
fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error())
59+
default:
60+
fmt.Println(aerr.Error())
61+
}
62+
} else {
63+
return err
64+
}
65+
}
66+
return nil
67+
}

database/dynamodb/listing.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package dynamodb
2+
3+
import (
4+
"Project/listing"
5+
"fmt"
6+
7+
"github.com/aws/aws-sdk-go/aws"
8+
"github.com/aws/aws-sdk-go/aws/awserr"
9+
"github.com/aws/aws-sdk-go/aws/session"
10+
"github.com/aws/aws-sdk-go/service/dynamodb"
11+
)
12+
13+
type droneListingRepository struct {
14+
sess *session.Session
15+
}
16+
17+
func NewDynamoListingRepository(sess *session.Session) listing.DroneRepository {
18+
return &droneListingRepository{
19+
sess,
20+
}
21+
}
22+
23+
func (r *droneListingRepository) FindAll() (drones []*listing.Drone, err error) {
24+
svc := dynamodb.New(r.sess)
25+
input := &dynamodb.ScanInput{
26+
TableName: aws.String("drones"),
27+
}
28+
29+
result, err := svc.Scan(input)
30+
if err != nil {
31+
if aerr, ok := err.(awserr.Error); ok {
32+
switch aerr.Code() {
33+
case dynamodb.ErrCodeProvisionedThroughputExceededException:
34+
fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error())
35+
case dynamodb.ErrCodeResourceNotFoundException:
36+
fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error())
37+
case dynamodb.ErrCodeRequestLimitExceeded:
38+
fmt.Println(dynamodb.ErrCodeRequestLimitExceeded, aerr.Error())
39+
case dynamodb.ErrCodeInternalServerError:
40+
fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error())
41+
default:
42+
fmt.Println(aerr.Error())
43+
}
44+
} else {
45+
// Print the error, cast err to awserr.Error to get the Code and
46+
// Message from an error.
47+
fmt.Println(err.Error())
48+
}
49+
return nil, err
50+
}
51+
52+
var droneList []*listing.Drone
53+
for _, element := range result.Items {
54+
var dron listing.Drone
55+
dron.ID = element["ID"].String()
56+
dron.Name = element["Name"].String()
57+
dron.Description = element["Description"].String()
58+
droneList = append(droneList, &dron)
59+
}
60+
return droneList, nil
61+
62+
}

database/redis/adding.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package redis
2+
3+
import (
4+
"Project/adding"
5+
"encoding/json"
6+
7+
"github.com/go-redis/redis"
8+
)
9+
10+
const table = "drones"
11+
12+
type droneAddingRepository struct {
13+
connection *redis.Client
14+
}
15+
16+
func NewRedisAddingRepository(connection *redis.Client) adding.DroneRepository {
17+
return &droneAddingRepository{
18+
connection,
19+
}
20+
}
21+
22+
func (r *droneAddingRepository) Create(drone *adding.Drone) error {
23+
encoded, err := json.Marshal(drone)
24+
25+
if err != nil {
26+
return err
27+
}
28+
29+
r.connection.HSet(table, drone.ID, encoded)
30+
return nil
31+
}

database/redis/listing.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package redis
2+
3+
import (
4+
"Project/listing"
5+
"encoding/json"
6+
7+
"github.com/go-redis/redis"
8+
)
9+
10+
//const table = "drones"
11+
12+
type droneListingRepository struct {
13+
connection *redis.Client
14+
}
15+
16+
func NewRedisListingRepository(connection *redis.Client) listing.DroneRepository {
17+
return &droneListingRepository{
18+
connection,
19+
}
20+
}
21+
22+
func (r *droneListingRepository) FindAll() (drones []*listing.Drone, err error) {
23+
const table = "drones"
24+
25+
ts := r.connection.HGetAll(table).Val()
26+
for key, value := range ts {
27+
t := new(listing.Drone)
28+
err = json.Unmarshal([]byte(value), t)
29+
30+
if err != nil {
31+
return nil, err
32+
}
33+
34+
t.ID = key
35+
drones = append(drones, t)
36+
}
37+
return drones, nil
38+
}

go.mod

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module Project
2+
3+
go 1.12
4+
5+
require (
6+
github.com/aws/aws-lambda-go v1.11.1
7+
github.com/aws/aws-sdk-go v1.20.15
8+
github.com/aws/aws-sdk-go-v2 v0.9.0
9+
github.com/go-redis/redis v6.15.2+incompatible
10+
github.com/google/uuid v1.1.1
11+
github.com/gorilla/mux v1.7.3
12+
github.com/lib/pq v1.1.1
13+
github.com/onsi/ginkgo v1.8.0 // indirect
14+
github.com/onsi/gomega v1.5.0 // indirect
15+
)

go.sum

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
github.com/aws/aws-lambda-go v1.11.1 h1:wuOnhS5aqzPOWns71FO35PtbtBKHr4MYsPVt5qXLSfI=
2+
github.com/aws/aws-lambda-go v1.11.1/go.mod h1:Rr2SMTLeSMKgD45uep9V/NP8tnbCcySgu04cx0k/6cw=
3+
github.com/aws/aws-sdk-go v1.20.15 h1:y9ts8MJhB7ReUidS6Rq+0KxdFeL01J+pmOlGq6YqpiQ=
4+
github.com/aws/aws-sdk-go v1.20.15/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
5+
github.com/aws/aws-sdk-go-v2 v0.9.0 h1:dWtJKGRFv3UZkMBQaIzMsF0/y4ge3iQPWTzeC4r/vl4=
6+
github.com/aws/aws-sdk-go-v2 v0.9.0/go.mod h1:sa1GePZ/LfBGI4dSq30f6uR4Tthll8axxtEPvlpXZ8U=
7+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
9+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
10+
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
11+
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
12+
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
13+
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
14+
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
15+
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
16+
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
17+
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
18+
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
19+
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
20+
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
21+
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
22+
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
23+
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
24+
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
25+
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
26+
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
27+
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
28+
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
29+
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
30+
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
31+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
32+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
33+
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
34+
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
35+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
36+
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
37+
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
38+
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
39+
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
40+
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
41+
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
42+
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
43+
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
44+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
45+
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
46+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
47+
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
48+
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
49+
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
50+
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
51+
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
52+
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
53+
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

handlers/apigatewayService/adding.go

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package apigatewayService
2+
3+
import (
4+
"Project/adding"
5+
"encoding/json"
6+
"net/http"
7+
8+
"github.com/aws/aws-lambda-go/events"
9+
"github.com/aws/aws-sdk-go-v2/aws/external"
10+
)
11+
12+
type AddingApiGateway interface {
13+
Create(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
14+
}
15+
16+
type droneAddingApiGateway struct {
17+
droneService adding.DroneService
18+
}
19+
20+
func NewAddingApiGateway(droneService adding.DroneService) AddingApiGateway {
21+
return &droneAddingApiGateway{
22+
droneService,
23+
}
24+
}
25+
26+
func (h *droneAddingApiGateway) Create(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
27+
28+
var drone adding.Drone
29+
30+
err := json.Unmarshal([]byte(request.Body), &drone)
31+
if err != nil {
32+
return events.APIGatewayProxyResponse{
33+
StatusCode: 400,
34+
Body: "Invalid payload",
35+
}, nil
36+
}
37+
38+
_ = h.droneService.CreateDrone(&drone)
39+
40+
response, _ := json.Marshal(drone)
41+
42+
_, err = external.LoadDefaultAWSConfig()
43+
if err != nil {
44+
return events.APIGatewayProxyResponse{
45+
StatusCode: http.StatusInternalServerError,
46+
Body: "Error while retrieving AWS credentials",
47+
}, err
48+
}
49+
if err != nil {
50+
return events.APIGatewayProxyResponse{
51+
StatusCode: http.StatusInternalServerError,
52+
Body: "Error while decoding to string value",
53+
}, err
54+
}
55+
56+
return events.APIGatewayProxyResponse{
57+
StatusCode: 200,
58+
Headers: map[string]string{
59+
"Content-Type": "application/json",
60+
},
61+
Body: string(response),
62+
}, nil
63+
}

0 commit comments

Comments
 (0)