היי! הרבה אנשים תהו איך לוח משימות פשוט או יישומים שמספקים תפקידים אלה עובדים. במאמר הזה, אני מזמין אתכם להביט כיצד תוכלו לכתוב מספר שירותים קטנים בגו, ולשים הכל בבסיס נתונים.
בואו נתחיל את המסע שלנו עם גולנג ו-MongoDB.
מדוע גולנג?
אני רוצה להראות את המפתחות:
- עיצוב מינימליסטי והיכולת להיכנס מהר
- מודל חזרה חזק עם גוראוטינים וערוצים
- מערכת עצומה
- רשת גדולה בעלת פתרון הולך-לפי
עוד אחד מהגורמים הוא לא לבזבז הרבה זמן בלמידה של ספקים או פתרונות פתוחים. במקרה שלי, אני רוצה ליצור שירות מיקרוסיבי שיעבד כמעט מאלפא. השפה הגולנגית יש לה הכל עבור זה.
אבל אני אשמור על המשמעות, שהשפה כבר עשירה בפרוייקטים מדהימים שפתרו המון בעיות עבור הפיתוחאים. פרוייקטים כמו:
- גין: פשוט רשת אינטרנט בעלת ביצועים גבוהים בגו
- ויפר: פתרון הגדרות (JSON, תפקידים, קומפוסים YML) ליישומים בגו
- גוארם: ספק אורך-משמעותי
- פרוטוקומפוס (פרוטוביפ): הדרך הטובה ביותר לסירלize מידע מבנה.
לא נבדוק אותם בתוך המסגרת המאמר, אך אולי אני אכתב עליהם מאוחר יותר. עם Protobuf, כבר כתבתי מאמר מעניין, "From JSON to FlatBuffers: Enhancing Performance in Data Serialization."
התקנה
התקנת השפה Go
בודקות golang.org והורשעת ההורדה. אחר כך, בתוך הטרמינל תבדוק.
go version
מערכת יישומים
פשוט התקנו VS Code (זה בחינם).
ואז תוספו הרחבה של Go:
תקייסו את הקוד הראשון שלכם:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
ובאמת תריצו אותו:
go run main.go
זה הכל! השלב הבא הוא לבחור את האפשרות הטובה ביותר לאסוף את המידע שלנו.
המבנה של המשימה שלנו
אני חושב שהמבנה הראשון שלנו צריך להיות מאוד פשוט. בואו נתחיל עם 3 שדות:
- שם (טקסט)
- תיאור (טקסט)
- מצב (בול)
קובץ JSON כמקור ההתבסס:
{
"title": "Go to the groceries",
"description": "Purchase milk, eggs, and bread",
"completed": false
}
מדוע MongoDB?
אנחנו צריכים לאסוף מידע עבור המשימות שלנו ולהיות גמישים. אנחנו לא צריכים ליצור סכם או יחסים בין דברים.
- גמישות סכם
- יכולת התארגנות הרוחצית: היא תומכת בהתארגנות הרוחצית באופן אופקי.
- שפת הבחינה העשירה
עבור השירות הקטן שלנו, אנחנו יכולים להפעיל אותו באמצעות docker-compose
.
# השתמשות במשתמש/סיסמא רוט/דוגמה
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"
.
ניתן לקרוא עוד בעזרת מדריך הגוונים בגו .
אחר כך, בואו נהיה מוקדים על סיפור אחד בלבד – הוספת משימות. עבור הוסף נסיונות ודגמאות מלאות קוד, בואו למאגר הגיתהביס Golang Workshop .
קישור לMongoDB
בעזרת שני תלויות בלבד, אנחנו יכולים ליצור קישור:
"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"`
}
משימה
– עבור בקשה HTTP,MongoTask
– עבור שכבת מונגודב: השימוש בשתי מבנים הוא קל מפני שלעולם איננו צריכים לשלוח מידע נוסף למשתמשים שלנו. לדוגמה, אולי יש לנו שדה מוסתר, כמו שם משתמש, שעלינו להחביא.
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,
}
// todo: ריצה שירות וכיבוי
}
ובואו נבדוק את זה עם בקשה הבאה:
# curl -X POST http://localhost:8080/add
#-H "Content-Type: application/json"
#-d '{
# "id": 1,
# "title": "קונה מוצרים לאוכל",
# "completed": false
#}'
POST http://localhost:8080/api/v1/add
Content-Type: application/json
{
"title": "Add description to the structure",
"description": "your desc here..."
}
זה כל זה. אחר כך, עלינו להוסיף ולהיות מיישמים של שיטות חדשות, והשירות שלנו יהיה מוכן לעבודה.
הסיכוי
יצרנו שירות מנהל משימות קטן אבן-עצמי בעזרת Golang וMongoDB.
כפי שאנו יכולים לראות, אם אנו צריכים לבנות שירות קטן, אנחנו עושים זאת מהר מאד וללא רבים מהמכשולים. במקרה שלי
אפשר גם לשים לב שזה לא יהיה יותר גרוע בשפות תכנות אחרות. במקומות מסוימים, זה אפילו מהר יותר. לדוגמה, אם אתה משתמש בפיתוני ובפסטAPI – וכאן אולי אני אתעצף איתך. השפה גולאנג עדיין מבוסס על הפרדיגמות של שפות תכנות כמו צייצ' וג' אווה, בהן יש OOP. מוצעים כמות הקוד והשיטות האלה מאפשרים לך לשמר את הקוד בעדינות ובנקירות כמו המצב האפשרי.
להתחיל, יהיה טוב להתחבר למשקלים כמו בסיס, שיעזרו לך להבין TDD ושיטות אחרות. אני גם אשייך שכדי להימנע מהרעיון של רעיון העלייה במאמר עם מדדים וטקסט, השתחררתי את ההשוואה לשפות אחרות. אני גם אשייך שלגולאנג אין בעיה עם זה, ואחרי שכתבת את הפונקציה העיקרית, אתה כבר מקבל אותה בתהליך הדיבור שלך. אתה יכול בקלות למצוא השוואות באינטרנט, כולל בניסויים.
עבור התחלת החיקוי ודגימות מקבלות לגמרי, ביקור באחד מהמאגרים GitHub (שהיה קישור לזה קודם).
תודה ותקווה לבריאות!
Source:
https://dzone.com/articles/build-a-to-do-list-with-mongodb-and-golang