Go Cloud Development Kit
Neste post vou falar sobre um projeto bem interessante que é mantido pelo time que desenvolve a linguagem Go. Trata-se do Go Cloud Development Kit, também conhecido como Go CDK.
O Go CDK fornece uma série de abstrações para um bom número de features bastante usadas em aplicações que rodam na nuvem, como banco de dados, armazenamento, mensageria, segredos, etc. O objetivo principal do projeto em criar estas abstrações é tornar o código independente de fornecedor de nuvem. Ao invés de tornar seu código dependente de uma solução, digamos o AWS S3, ao usar o Go CDK seria facilmente possível alterar para outro fornecedor, como o Google Cloud Storage.
Mas você pode estar se perguntando algo como:
Ok, legal. Mas na prática dificilmente eu vou mudar de fornecedor. Porque vale a pena usar algo assim?
Além desta opção, eu consigo ver outras vantagens em se usar o Go CDK:
- Escrita de testes. Usando as abstrações é bem simples podermos usar um armazenamento em memória nos testes, enquanto que no ambiente de produção usamos o provedor de nuvem;
- Diferentes ambientes. Podemos usar um fornecedor mais barato em um ambiente de testes/homologação e outro mais robusto e caro no ambiente de produção
- Evolução. É possível que a sua aplicação comece com uma solução mais simples, digamos o SQS para pub/sub, e conforme a carga e a complexidade aumentar pode-se mudar a decisão e começar a usar o Kafka.
Para exemplificar, vejamos o código a seguir:
package main
import (
"context"
"fmt"
"gocloud.dev/blob"
"gocloud.dev/blob/memblob"
)
func main() {
ctx := context.Background()
// Create an in-memory bucket.
bucket := memblob.OpenBucket(nil)
defer bucket.Close()
key := "my-key"
text := []byte("hello world")
// Now we can use bucket to read or write files to the bucket.
err := write(ctx, bucket, key, text)
if err != nil {
panic(err)
}
data, err := read(ctx, bucket, key)
if err != nil {
panic(err)
}
fmt.Println(string(data))
}
func write(ctx context.Context, bucket *blob.Bucket, key string, text []byte) error {
err := bucket.WriteAll(ctx, key, text, nil)
return err
}
func read(ctx context.Context, bucket *blob.Bucket, key string) ([]byte, error) {
return bucket.ReadAll(ctx, key)
}
No código estamos escrevendo e lendo de um documento que foi armazenado em um bucket
em memória. Para mudarmos a decisão e usarmos o S3
é necessário apenas mudar o trecho abaixo na função main:
sess, err := session.NewSession(&aws.Config{
Region: aws.String("us-west-1"),
})
sess, err = session.NewSessionWithOptions(session.Options{
Profile: "profile_name_configured_in_your_machine",
Config: aws.Config{
Region: aws.String("us-east-1"),
},
})
if err != nil {
panic(err)
}
bucket, err := s3blob.OpenBucket(ctx, sess, "post-go-cdk", nil)
if err != nil {
panic(err)
}
defer bucket.Close()
Estamos apenas configurando a conexão com o S3
e criando um bucket
neste fornecedor. O restante do código não muda, continuamos usando as funções read
e write
.
Atualmente o projeto possui abstrações para:
- Blob, ou seja, armazenamento de arquivos. Possui suporte para Google Cloud Storage, S3, Azure Blob Storage e armazenamento local.
- Docstore, ou seja, bancos de dados de documentos, com suporte para Google Cloud Firestore, Amazon DynamoDB, Azure Cosmos DB, MongoDB e armazenamento em memória.
- MySQL/PostgreSQL, com suporte a bancos locais, GCP Cloud SQL, AWS RDS e Azure Database.
- Pub/Sub. Talvez a mais completa, com suporte a Google Cloud Pub/Sub, Amazon Simple Notification Service (SNS), Amazon Simple Queue Service (SQS), Azure Service Bus, RabbitMQ, NATS, Kafka e armazenamento em memória.
- Entre outros.
E além de código o site oficial tem uma área com alguns conceitos importantes.
Apesar de ser um projeto ainda em estágios iniciais (o último release no momento da escrita deste post é o 0.28), é um projeto que está em evolução e bem ativo, além de ser mantido pelo time da própria linguagem. Por isso acredito que vale muito o investimento e uso para abstrair as complexidades que comentei neste post.