こんにちは!多くの人が簡単なタスクシートやそのような機能を提供するアプリケーションの仕組みに好奇になっています。この記事で、私はあなたが数時間で小型サービスのGoコードを書いて、全てをデータベースに入れる方法を考えていただけることを約束します。
ここで、GolangとMongoDBを使って冒険を始めましょう。
なぜGolangを選んだのでしょうか?
私は主要な利点を紹介したいと思います。
- 最小限の設計と速いコンパイル
- Goroutinesとチャンネルを持つ強力な並行モデル
- 大きな生態系
- パッケージからはじめたら跨平台
もう一つの要因は、ライブラリやオープンソースの解決策に多くの時間を費やす必要がないことです。私の場合、ほとんどの場で外から始動するマイクロサービスを作りたいと考えています。Golangプログラミング言語はこれに完璧に適しています。
しかし、言語にはすでに非常に素晴らしいプロジェクトが多く、開発者の多くの問題を解決しています。このようなプロジェクトを例に挙げます。
- Gin: 高性能のHTTPウェブフレームワーク
- Viper: Goアプリケーション用の設定解決策(JSON、プロperties、YMLファイル)
- GORM: ORMライブラリ
- Protocol Buffers (Protobuf): 構造化されたデータを序列化する最善の方法
この記事の枠内ではレビューしないが、もしかしたら後で何か書くかもしれない。Protobufについては、すでに興味深い記事「FFrom JSON to FlatBuffers:“
インストール
Go言語のインストール
golang.orgにアクセスし、ダウンロードします。
go version
IDE
Just install VS Code (it’s free).
And add the Golang extension:
Type your first code:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
And run it:
go run main.go
That’s it!
タスクの構造
最初の構造はとてもシンプルであるべきだと思います。
- Title (text)
- Description (text)
- Status (bool)
参考としてJSONファイル:
{
"title": "Go to the groceries",
"description": "Purchase milk, eggs, and bread",
"completed": false
}
なぜMongoDBなのか?
私たちはタスクに适したデータを集め、柔軟性が必要です。物と物の間にスキーマや関連性を作成する必要はありません。
- 柔軟なスキーマ
- スケーラビリティ: 水平スケーリングをサポートします。
- 豊富なクエリ言语
私たちの小さなサービスでは、docker-compose
で実行できます。
# ルート/exampleをユーザー/パスワード資格情報として使用してください
version: '3.1'
services:
mongo:
image: mongo
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
私は、私たちのデータ(コレクション、データベースなど)と共に作业するためにCompass GUIをお好みです。ここでダウンロードしてください。
単に実行し、 “詳細設定” にあなたの資格情報を設定してください。これは完璧に機能し、必要であれば問題を見つけたり、リクエストを最適化します。
システム設計(本当に小さい)
私たちのサービスにおいて、当然、最良の選択はCRUD(作成、読み取り、更新、削除)メソッドを作成することです。こんな感じ(削除を除く):
http.HandleFunc("/api/v1/add", todoHandler.AddTask)
http.HandleFunc("/api/v1/get-all", todoHandler.GetAllTasks)
http.HandleFunc("/api/v1/update", todoHandler.UpdateTask)
http.HandleFunc("/api/v1/complete", todoHandler.CompleteTask)
私はすべての責任をフォルダーに分離する方法を使用したいです。
- ハンドラー – HTTP層
- モデル – データの構造
- 使用例 – サービスとレポジトリを含むビジネス層
プロジェクトの構造はこのようになるかもしれません:
todo-list/
│
├── cmd/
│ └── main.go
├── pkg/
│ └── handler
│ └── add_task.go
│ └── http_handler.go
│ └── complite_task.go
│ └── get_all_task.go
│ └── update_task.go
│ └── mapper
│ └── task.go
│ └── model
│ └── task.go
│ └── usecase
│ └── task
│ └── repository
│ └── add_task.go
│ └── complite_task.go
│ └── get_all_task.go
│ └── mongo_repositiry.go
│ └── repository.go
│ └── update_task.go
│ └── service
│ └── add_task.go
│ └── complite_task.go
│ └── get_all_task.go
│ └── service.go
│ └── update_task.go
└── go.mod
見ての通り、私たちには “go.mod” ファイルがありますが、それは何でしょうか?それはパッカーマネージャーまたは依存関係マネージャーです。私たちは外部のライブラリをインストールし、追加し、それらを使用することができます。私たちの例では、いくつかのコマンドを使用して “go mod” を必要とします。
- アプリを初期化する ->
go mod init todo-service
。私たちはすべてのものを初期化し、依存関係マネージャーは必要なファイルを作成し、私たちが必要とするすべてのものを追加します。 - “go mod add “link”” を使用して追加の依存関係を追加する ->
詳細は Go Modules Reference ページを読むことができます。
次に、一度だけメソッドを焦点に置きましょうータスクの追加。完全なコードの例を見るには、GitHub リポジトリ Golang Workshop に行ってください。
MongoDBへの接続
2つの依存関係だけを使用して接続を作成できます。
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
もちろん、私たちのサービスに追加する必要があります。以下のコマンドを使用してください。
go get "go.mongodb.org/mongo-driver/mongo"
および
go get "go.mongodb.org/mongo-driver/mongo/options"
次に、以下のコードを書いてください。
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// MongoDBクライアントのオプションを設定する
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017").SetAuth(options.Credential{
Username: "root",
Password: "example",
})
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal(err)
}
log.Println("Connected to MongoDB!")
}
私たちのアプリのためのデータ構造:
package model
import "go.mongodb.org/mongo-driver/bson/primitive"
type Task struct {
ID string `json:"id"`
Title string `json:"title"`
Desciption string `json:"description"`
Completed bool `json:"completed"`
}
type MongoTask struct {
ID primitive.ObjectID `json:"id" bson:"_id"`
Title string `json:"title"`
Desciption string `json:"description"`
Completed bool `json:"completed"`
}
Task
– HTTP要求に対するMongoTask
はMongoDB層に対応しています: この2つの構造を使用するのは簡単です、なぜなら私たちが追加のデータをユーザーに送信する必要がない場合があるからです。たとえば、秘密のフィールドがある場合があり、これは「ユーザー名」のように隠す必要があります。
1. リポジトリー層:
type Repository interface {
AddTask(ctx context.Context, task model.MongoTask) error
}
func (r *MongoRepository) AddTask(ctx context.Context, task model.MongoTask) error {
task.ID = primitive.NewObjectID()
_, err := r.collection.InsertOne(ctx, task)
}
2. サービス層:
type TodoService interface {
AddTask(ctx context.Context, task model.Task) error
}
func (s *Service) AddTask(ctx context.Context, task model.Task) error {
return s.Repo.AddTask(ctx, mapper.MapToDto(task))
}
3. ハンドラー層(HTTP要求を処理する):
func (h *Handler) AddTask(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
var task model.Task
err := json.NewDecoder(r.Body).Decode(&task)
if err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
err = h.Service.AddTask(ctx, task)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusCreated)
}
今、main.go
ファイルでデータベース接続をインストールし、「層」の依存関係を初期化する必要があります。
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// MongoDBクライアントオプションを設定
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017").SetAuth(options.Credential{
Username: "root",
Password: "example",
})
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal(err)
}
log.Println("Connected to MongoDB!")
// リポジトリー、サービス、およびハンドラーを初期化
todoRepo := repository.NewMongoRepository(client)
todoService := service.NewService(todoRepo)
todoHandler := handler.NewHandler(todoService)
// ルートを設定
http.HandleFunc("/api/v1/add", todoHandler.AddTask)
// サーバーを作成
srv := &http.Server{
Addr: ":8080",
Handler: nil,
}
// サービスを実行して終了
}
そして、以下の要求でテストします。
# curl -X POST http://localhost:8080/add
#-H "Content-Type: application/json"
#-d '{
# "id": 1,
# "title": "Buy groceries",
# "completed": false
#}'
POST http://localhost:8080/api/v1/add
Content-Type: application/json
{
"title": "Add description to the structure",
"description": "your desc here..."
}
}’That’s all. Then, we must add and implement new methods, and our service will be ready to work.
結論
GolangとMongoDBを使用して小さくても強力なタスク管理サービスを作成しました。
私たちが小さなサービスを作成する必要がある場合、多くの障碍なく素早く作成できることがわかります。私の場合、ドキュメントを持つ場合はMongoDBを主なデータベースとして使用したいと思います。管理が簡単です。
他のプログラミング言語に比べても劣くはないし、いくつかの場ではより速いこともある。たとえば、PythonとFastAPIを使用しているときにも、ここであなたと同意することがあり得ます。Go言語は、C++やJavaのようなプログラミング言語のパラダイムに基づいていますので、OOPがあります。このようなコードと方法論は、可能な限りコードを明確かつクリーンに保ちます。
始めに、基本的な要素を掌握することが重要であり、TDDや他の方法論を理解するのを助けることができます。また、記事に指标やテキストを充てていないようにして、他の言語との性能比較を省くことに注意しています。Golangはこの点で問題がないこと、主要な関数を書いた後、すでにスレッド内で実行できること、インターネット上に、ベンチマークを含む比較が簡単に見つけられることを指摘します。
さらなる探索や完全なコード例を見るには、以前にリンクされたGitHubレポジトリに行ってください。
ありがとうございます。お互いに注意を払いましょう!
Source:
https://dzone.com/articles/build-a-to-do-list-with-mongodb-and-golang