מיוצא לעומת לא מיוצא
חלק מהיחידה לוגיקה וזרימת התוכנית במסלול ה-GO של Coddy. שיעור 52 מתוך 68.
ב-Go, הנראות של מזהים (משתנים, פונקציות, טיפוסים וכו׳) נקבעת לפי מוסכמת שמות פשוטה. היא קובעת אם קוד מחבילות אחרות יכול לגשת למזהים שלך.
מזהים מיוצאים מתחילים באות גדולה ונגישים מחבילות אחרות. אפשר לחשוב עליהם כעל ״ציבוריים״ — כל מי שמייבא את החבילה שלך יכול להשתמש בהם.
// אלה מיוצאים (ציבוריים)
var Name string
func Calculate() int
type Person structמזהים שאינם מיוצאים מתחילים באות קטנה ונגישים רק בתוך אותה חבילה. הם "פרטיים" לחבילה שלך.
// אלה אינם מיוצאים (פרטיים)
var age int
func helper() string
type config structמוסכמת השמות הזאת היא הדרך של Go לשלוט בגישה בלי להזדקק למילות מפתח כמו public או private. כשתנסה להשתמש במזהה לא מיוצא מחבילה אחרת, Go תציג שגיאת קומפילציה, משום שהמזהה הזה אינו גלוי מחוץ לחבילה שלו.
אתגר
קלתקן את בעיות החשיפה בחבילת Go על ידי תיקון מוסכמת השמות של מזהים מיוצאים ולא מיוצאים. תעבוד עם תרחיש מדומה של כמה חבילות, שבו חלק מהמזהים קיבלו שמות שגויים, מה שגורם לשגיאות הידור כאשר מנסים לגשת אליהם מחבילות אחרות.
תקבל שני קלטים:
- מחרוזת שמכילה הגדרות של חבילות בפורמט
"package_name:identifier1:type1:visibility1,identifier2:type2:visibility2|package_name:identifier1:type1:visibility1"(לדוגמה,"utils:helper:function:private,Calculate:function:public|main:name:variable:private,Version:variable:public") - מחרוזת שמכילה ניסיונות גישה בפורמט
"accessing_package.identifier1,accessing_package.identifier2,accessing_package.identifier3"(לדוגמה,"main.helper,main.Calculate,utils.Version")
המשימה שלך היא:
- לנתח את הקלט הראשון על ידי פיצול לפי קווים אנכיים כדי לקבל הגדרות נפרדות של חבילות
- עבור כל הגדרת חבילה, לפצל לפי נקודתיים כדי לקבל את שם החבילה ואת המזהים שלה
- עבור כל הגדרת מזהה, לפצל לפי נקודתיים כדי לקבל את שם המזהה, את הסוג ואת החשיפה המיועדת
- ליצור פונקציה בשם
fixIdentifierNameשמקבלת שם של מזהה ואת החשיפה המיועדת, ומחזירה את השם המתוקן:- אם החשיפה היא
"public", לוודא שהמזהה מתחיל באות גדולה - אם החשיפה היא
"private", לוודא שהמזהה מתחיל באות קטנה
- אם החשיפה היא
- להציג את כותרת ניתוח החבילות:
"=== PACKAGE VISIBILITY ANALYSIS ===" - עבור כל חבילה, להציג את פרטי החבילה:
"Package: [package_name]"- עבור כל מזהה בחבילה:
- אם צריך לתקן את שם המזהה:
"- [original_name] ([type]) -> [corrected_name] (visibility: [visibility])" - אם שם המזהה תקין:
"- [identifier_name] ([type]) (visibility: [visibility]) ✓"
- אם צריך לתקן את שם המזהה:
- לנתח את הקלט השני על ידי פיצול לפי פסיקים כדי לקבל ניסיונות גישה נפרדים
- עבור כל ניסיון גישה, לפצל לפי נקודות כדי לקבל את החבילה שמנסה לגשת ואת המזהה שאליו ניגשים
- להציג את כותרת אימות הגישה:
"=== ACCESS VALIDATION ===" - עבור כל ניסיון גישה, לקבוע אם הגישה תקינה:
- למצוא את החבילה שמכילה את המזהה
- לבדוק אם שם המזהה המתוקן מתחיל באות גדולה (מיוצא)
- אם המזהה מיוצא:
"[accessing_package] accessing [target_package].[corrected_identifier_name]: ✓ ALLOWED (exported)" - אם המזהה אינו מיוצא:
"[accessing_package] accessing [target_package].[corrected_identifier_name]: ✗ DENIED (unexported)" - אם המזהה לא קיים:
"[accessing_package] accessing unknown.[identifier_name]: ✗ NOT FOUND"(להדפיס את המילהunknownכשם החבילה; ניסיון זה נספר כגישה שנדחתה)
- לספור ולהציג את נתוני הסיכום:
"=== SUMMARY ===""Total packages analyzed: [number_of_packages]""Total identifiers processed: [total_number_of_identifiers]""Identifiers requiring fixes: [number_of_identifiers_that_needed_fixing]""Access attempts: [number_of_access_attempts]""Allowed accesses: [number_of_allowed_accesses]""Denied accesses: [number_of_denied_accesses]"
- להציג את ההמלצות הסופיות:
- אם היו מזהים שנדרש לתקן:
"Recommendation: Fix identifier naming to follow Go conventions" - אם כל המזהים היו תקינים:
"All identifiers follow proper Go naming conventions"
- אם היו מזהים שנדרש לתקן:
יש להשתמש בחבילת strings כדי לפצל את מחרוזות הקלט, בחבילת fmt עבור פלט מעוצב, ובפונקציות לעיבוד מחרוזות כדי לבדוק ולשנות שמות של מזהים. האתגר הזה מדגים כיצד מוסכמת השמות של Go קובעת את החשיפה של חבילות ועוזר לך להבין את ההבדל בין מזהים מיוצאים למזהים שאינם מיוצאים.
נסו בעצמכם
package main
import (
"fmt"
"strings"
)
func main() {
// קרא את הקלט
var packageDefinitions string
var accessAttempts string
fmt.Scanln(&packageDefinitions)
fmt.Scanln(&accessAttempts)
// TODO: כתוב את הקוד שלך למטה
// צור את הפונקציה fixIdentifierName
// נתח את הגדרות החבילות
// הצג את ניתוח החבילות
// נתח את ניסיונות הגישה
// הצג את אימות הגישה
// חשב והצג נתונים סטטיסטיים מסכמים
// הצג המלצות
}השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה לוגיקה וזרימת התוכנית
1בקרת זרימה מתקדמת
switch עם `fallthrough`יציאה מלולאות מקוננותהמשך לולאה מסוימתהצהרת `goto`סיכום – שליטה מתקדמת בלולאות4פרויקט: רשימת משימות פשוטה
הגדרת הפרויקטהוספת משימה2מבנים ושיטות
הגדרת שיטות במבניםמקבלי ערךמקבלי מצביעבחירת מקבליםשיטות לעומת פונקציותסיכום — התנהגות המבנים5מפות לעומק
מפות של Structsמצביעים כערכים במפהבדיקה אם מפות הן nilהשוואת מפותסיכום - מונה תדירות מילים8פרויקט: ניהול מלאי פשוט
סקירת הפרויקטבדיקת המלאי3ממשקים (הבסיס)
מהו ממשק?הגדרת ממשקמימוש ממשקשימוש בטיפוסי ממשקממשק ריקבדיקות טיפוסמתג טיפוסיםסיכום – צורות והתנהגויות6קבוצות בסגנון המקובל ב-Go
דפוס הקבוצה ב-Goיצירת קבוצההוספה לקבוצהבדיקת חברות בקבוצההסרה מקבוצהמעבר על איברי קבוצהסיכום – שמות משתמש ייחודיים9חבילות ותחום נראות
מהי חבילה?מיוצא לעומת לא מיוצאיצירת חבילה פשוטהכינוי לחבילההמזהה הריק `_`הפונקציה `init`סיכום – בניית כלי עזרתרגלו בעצמכם: קומפיילר Go אונליין