מערכת השאלת ספרים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 100 מתוך 107.
אתגר
קלבואו נבנה את מערכת השאלת הספרים בפרויקט ניהול הספרייה שלנו! תיצרו מבנה Library שינהל אוספים של ספרים ומשתמשים, עם מתודות לטיפול בהשאלה ובהחזרה, כולל אימות מתאים.
תארגנו את הקוד שלכם בארבעה קבצים:
book.go: מבנהBookמהשיעור הקודם, עם השדותID,Title,Author,ISBNו-Available. הוסיפו את הבנאיNewBook, שמאתחל ספרים כזמינים.user.go: מבנהUserעםID,Name,Emailו-BorrowedBooks(פרוסה של מזהי ספרים). הוסיפו את הבנאיNewUser, שמאתחל משתמשים עם רשימת השאלות ריקה.library.go: צרו מבנהLibraryששומר ספרים ומשתמשים במפות (כאשר המפתחות הם המזהים שלהם). בנו את הרכיבים הבאים:- בנאי
NewLibraryשמאתחל מפות ריקות לספרים ולמשתמשים - מתודת
AddBookשמוסיפה ספר לספרייה - מתודת
AddUserשמוסיפה משתמש לספרייה - מתודת
Borrowשמקבלת מזהה משתמש ומזהה ספר, מאמתת את הפעולה, מסמנת את הספר כלא זמין, מוסיפה את מזהה הספר לרשימת הספרים שהמשתמש השאיל, ומחזירה שגיאה אם משהו משתבש - מתודת
Returnשהופכת את תהליך ההשאלה: מסמנת את הספר כזמין ומסירה אותו מרשימת הספרים שהמשתמש השאיל
מתודת
Borrowצריכה להחזיר את השגיאות הבאות:user not foundאם מזהה המשתמש לא קייםbook not foundאם מזהה הספר לא קייםbook not availableאם הספר כבר הושאל
מתודת
Returnצריכה להחזיר את השגיאות הבאות:user not foundאם מזהה המשתמש לא קייםbook not foundאם מזהה הספר לא קייםbook not borrowedאם הספר כבר זמין
- בנאי
main.go: חברו את הכול יחד על ידי יצירת ספרייה, הוספת ספרים ומשתמשים, ואז עיבוד פעולות השאלה והחזרה.קראו את מספר הספרים, ואז עבור כל ספר קראו את המזהה, הכותרת, המחבר ומספר ה-ISBN שלו. לאחר מכן קראו את מספר המשתמשים, ועבור כל משתמש קראו את המזהה, השם וכתובת האימייל שלו. לאחר מכן קראו את מספר הפעולות, כאשר כל פעולה היא
borrow [userID] [bookID]אוreturn [userID] [bookID].עבור כל פעולה, הדפיסו
OKאם היא הצליחה, אוError: [message]אם היא נכשלה.
הקלטים הבאים יסופקו:
- מספר הספרים, ולאחר מכן המזהה, הכותרת, המחבר ומספר ה-ISBN של כל ספר (כל אחד בשורה נפרדת)
- מספר המשתמשים, ולאחר מכן המזהה, השם וכתובת האימייל של כל משתמש (כל אחד בשורה נפרדת)
- מספר הפעולות, ולאחר מכן כל פעולה בשורה נפרדת
לדוגמה, עבור הקלט:
2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.com
4
borrow U001 B001
borrow U001 B001
return U001 B001
borrow U002 B001הפלט שלכם צריך להיות:
OK
Error: book not available
OK
Error: user not foundועבור הקלט:
1
B100
Design Patterns
Gang of Four
978-0201633610
2
U001
Bob Jones
bob@email.com
U002
Carol White
carol@email.com
3
borrow U001 B100
borrow U002 B100
return U001 B100הפלט שלכם צריך להיות:
OK
Error: book not available
OKועבור הקלט:
1
B001
Go in Action
William Kennedy
978-1617291784
1
U001
Dave Miller
dave@test.com
2
return U001 B001
borrow U001 B999הפלט שלכם צריך להיות:
Error: book not borrowed
Error: book not foundשימו לב איך ה-Library משמשת כמתאמת המרכזית. היא מאמתת את כל הפעולות לפני שינוי המצב, וכך מוודאת שהספרים והמשתמשים נשארים מסונכרנים. שימוש במקבלי מצביע מאפשר למתודות שלכם לשנות את הנתונים עצמם שנשמרים במפות!
נסו בעצמכם
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// קרא את מספר הספרים
var numBooks int
fmt.Fscanln(reader, &numBooks)
// TODO: צור ספרייה חדשה
// TODO: קרא את הפרטים של כל ספר (ID, Title, Author, ISBN בשורות נפרדות)
// והוסף אותם לספרייה
for i := 0; i < numBooks; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
author, _ := reader.ReadString('\n')
author = strings.TrimSpace(author)
isbn, _ := reader.ReadString('\n')
isbn = strings.TrimSpace(isbn)
// TODO: צור ספר והוסף אותו לספרייה
}
// קרא את מספר המשתמשים
var numUsers int
fmt.Fscanln(reader, &numUsers)
// TODO: קרא את הפרטים של כל משתמש (ID, Name, Email בשורות נפרדות)
// והוסף אותם לספרייה
for i := 0; i < numUsers; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
email, _ := reader.ReadString('\n')
email = strings.TrimSpace(email)
// TODO: צור משתמש והוסף אותו לספרייה
}
// קרא את מספר הפעולות
var numOps int
fmt.Fscanln(reader, &numOps)
// TODO: עבד כל פעולה
// פורמט: "borrow [userID] [bookID]" או "return [userID] [bookID]"
for i := 0; i < numOps; i++ {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
parts := strings.Split(line, " ")
// TODO: נתח את הפעולה וקרא למתודה המתאימה
// הדפס "OK" במקרה של הצלחה או "Error: [message]" במקרה של כישלון
}
}
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות OOP ב-Go
קבצים חיצונייםסביבת העבודה והמודולים של Goחבילות וייבואשמות מיוצאים לעומת שמות לא מיוצאיםמבוא ל-OOP ב-GoStructs כמחלקותהגדרת מתודות עבור Structsמקבלי Pointer לעומת Valueאתחול Structפונקציות Constructorחזרה – מחשבון פשוט4ממשקים
מבוא לממשקיםמימוש משתמעממשק כחוזהממשק ריק (any)אימות טיפוסמתג טיפוסיםהרכבת ממשקיםממשקי Stringer ו-Errorסיכום – מחשבון צורות7כימוס
שדות מיוצאים לעומת שדות לא מיוצאיםכימוס ברמת החבילהמתודות Getter ו-Setterהסתרת מידע ב-Goסיכום – רשומות תלמידים10Generics (Go 1.18 ומעלה)
מבוא ל־Genericsפרמטרים של טיפוסיםאילוצי טיפוסיםמבנים גנרייםפתרון עוקף למתודות גנריותסיכום – אוסף גנרי2העמקה בסוגים וב-Structs
סוגים בסיסיים ומורכביםהגדרות של סוגים מותאמים אישיתתגיות StructStructs אנונימייםStructs מקונניםערכי אפס וברירות מחדלסיכום – ספר אנשי קשר5קומפוזיציה במקום ירושה
למה ב-Go אין ירושהיסודות הטמעת Structקידום מתודותהטמעת כמה Structsהטמעה לעומת אגרגציההסתרת מתודות מוטמעותסיכום – היררכיית עובדים8טיפול בשגיאות ו-OOP
ממשק errorסוגי שגיאות מותאמים אישיתעטיפת שגיאות (fmt.Errorf)שגיאות Sentinelerrors.Is() ו-errors.As()Panic, Defer ו-Recoverסיכום – מנתח קבצים11ספרייה סטנדרטית ותכנות מונחה עצמים
io.Reader ו-io.Writersort.Interfaceהממשק fmt.Stringerencoding/json עם מבניםהממשק http.Handlerסיכום – מודלים של REST API3מצביעים וזיכרון
יסודות המצביעים ב-Goמצביעים למבניםהעברה לפי ערך לעומת לפי הפניההפונקציה new()איסוף אשפה ב-Goסיכום - בונה רשימה מקושרת6פולימורפיזם ב-Go
פולימורפיזם באמצעות ממשקיםטיפוס ברווז ב-Goכללי התאמה לממשקאוספים פולימורפייםהזרקת תלויותסיכום - מעבד תשלומים9מקביליות ו-OOP
יסודות GoroutinesChannels ותקשורתChannel עם חוצץ לעומת ללא חוצץפקודת Selectsync.Mutex ו-sync.RWMutexsync.WaitGroupתכנון Struct בטוח לשימוש במקבילסיכום - מאגר עובדים12מושגים מתקדמים בתכנות מונחה עצמים
דפוס האפשרויות הפונקציונליותדפוס Builder ב-Goשרשור מתודותכינויי טיפוסים לעומת הגדרותיסודות Reflectionסקירה כללית של יצירת קוד15פרויקט: ניהול ספרייה
סקירה כללית ומבנה הפרויקטמבני נתונים של ספרים ומשתמשיםתרגלו בעצמכם: קומפיילר Go אונליין