שלום לכולם,
הגיע הזמן שנעשה איזה פוסט על שפת go
כשמחפשים בגוגל לחפש ערך: golang
קצת על go מויקיפדיה:
“GO היא שפת תכנות התומכת במובהק בעיבוד מקבילי ובעלת תמיכה חלקית בתכנות מונחה-עצמים, בעלת טיפוסיות סטטית ובטוחה ותחביר הדומה לזה של שפת C. השפה מעוצבת על ידי חברת גוגל.”
בטוח שיצא לכם בכל שפה ו\או טכנולוגיה, לכתוב אפליקציה שרצה או על המחשב המקומי או מרוחק ומציגה או שולחת במייל כמה מקום פנוי יש בכוננים.
אז קודם כל, אני משתמש בwin 32 API (בפוסט הזה לא נרחיב בנושא)
בדוגמא שלנו, אני מציג כמה יכולות של go,
דוגמאות מלאות יותר ניתן למצוא בלינק הבא http://tour.golang.org/#1
לצורך הבהרה: Package = חבילה
1 |
fmt.Println("Hello, 世界") |
זאת דוגמא של hello world
שורה הנ”ל מכילה 2 אובייקטים:
Fmt – חבילה שמממשת כתיבות IO עיצוביות למסך
Println – מתודה שכותבת למסך, בדוגמא שלנו string פשוט
http://golang.org/pkg/fmt/#Println
ועכשיו לחלק המעניין יותר של הפוסט
בחלק הזה יש חלקים עיקריים:
1. לקבל רשימה של כוננים שיש במחשב
2. לקבל אינפורמציה עבור כל כונן
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
func GetLogicalDrives() []string { kernel32 := syscall.MustLoadDLL("kernel32.dll") GetLogicalDrives := kernel32.MustFindProc("GetLogicalDrives") n, _, _ := GetLogicalDrives.Call() s := strconv.FormatInt(int64(n), 2) var drives_all = []string{"A:", "B:", "C:", "D:", "E:", "F:", "G:", "H:", "I:", "J:", "K:", "L:", "M:", "N:", "O:", "P:", "Q:", "R:", "S:", "T:", "U:", "V:", "W:", "X:", "Y:", "Z:"} temp := drives_all[0:len(s)] var d []string for i, v := range s { if v == 49 { l := len(s) - i - 1 d = append(d, temp[l]) } } var drives []string for i, v := range d { drives = append(drives[i:], append([]string{v}, drives[:i]...)...) } return drives } |
פונקציה GetLogicalDrives, לא מקבלת שום פלט, אך מחזירה מערך של strings
1 |
kernel32 := syscall.MustLoadDLL("kernel32.dll") |
http://golang.org/pkg/syscall/
טוען את kernel32.dll עבור win 32 API.
1 |
GetLogicalDrives := kernel32.MustFindProc("GetLogicalDrives") |
מקבל מצביע למתודה.
1 2 |
n, _, _ := GetLogicalDrives.Call() s := strconv.FormatInt(int64(n), 2) |
אחרי שמריצים את GetLogicalDrives, מקבלים 1000100, bitmap של כוננים.
אחרי לולאות ופרסור, הdrives מכיל רשימה של כוננים עם [c:,g:]
חזרה לmain
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
func main() { fmt.Println("Hello, 世界") DrivesList := GetLogicalDrives() kernel32, _ := syscall.LoadLibrary("kernel32.dll") defer syscall.FreeLibrary(kernel32) GetDiskFreeSpaceEx, _ := syscall.GetProcAddress(syscall.Handle(kernel32), "GetDiskFreeSpaceExW") for _, drive := range DrivesList { lpFreeBytesAvailable := int64(0) lpTotalNumberOfBytes := int64(0) lpTotalNumberOfFreeBytes := int64(0) _, _, _ = syscall.Syscall6(uintptr(GetDiskFreeSpaceEx), 4, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(drive))), uintptr(unsafe.Pointer(&lpFreeBytesAvailable)), uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)), uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)), 0, 0) fmt.Printf("Disk Name %s\n", drive) fmt.Printf("Available %dmb\n", lpFreeBytesAvailable/1024/1024.0) fmt.Printf("Total %dmb\n", lpTotalNumberOfBytes/1024/1024.0) fmt.Printf("Free %dmb\n", lpTotalNumberOfFreeBytes/1024/1024.0) } } |
נריץ את GetDiskFreeSpaceEx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx
ממש לפי הAPI
1 2 3 4 5 6 |
BOOL WINAPI GetDiskFreeSpaceEx( _In_opt_ LPCTSTR lpDirectoryName, _Out_opt_ PULARGE_INTEGER lpFreeBytesAvailable, _Out_opt_ PULARGE_INTEGER lpTotalNumberOfBytes, _Out_opt_ PULARGE_INTEGER lpTotalNumberOfFreeBytes ); |
מריצים לולאה על גבי רשימת הכוננים
עבור כל כונן, נריץ את GetDiskFreeSpaceEx
שמקבל פרמטר אחד שזה שם כונן, ו3 פרמטרים של גדלים שחוזרים מהמתודה.
1 |
syscall.Syscall6 |
נריץ לפי API את
1 |
func Syscall6(trap, nargs ,a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) |
1 2 3 4 5 6 7 8 9 10 11 |
_, _, _ = syscall.Syscall6( trap = uintptr(GetDiskFreeSpaceEx), nargs = 4 , a1 = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(drive))), a2 = uintptr(unsafe.Pointer(&lpFreeBytesAvailable)), a3 = uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)), a4 = uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)), a5 = 0, a6 = 0 ) |
משמעות מספר 6 בשם syscall שזה יהיה לפי נוסחה הבא
1 |
<span style="color: #222222;">Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)</span> |
trap = מחזיק את הכתובת של procedure הרצוי
Nargs = שווה לכמות הפרמטרים שיש לפונקציה שלנו (במקרה שלנו 4)
1 2 |
unsafe.Pointer unsafe.Pointer(&lpFreeBytesAvailable) |
מייצר מצביע בזיכרון עבור הפרמטר הרלוונטי.
מידע נוסף ניתן לקבל בלינקים הבאים:
http://www.goinggo.net/2013/07/understanding-pointers-and-memory.html
את התוצאות נדפיס ישר למסך, בעזרת חבילת fmt.
הערות:
1. איך עושים foreach בgo
1 2 3 |
for _, drive := range DrivesList { fmt.Printf("Disk Name %s\n", drive) } |
2. בפוסט השתמשתי בMustLoadDLL ו גם LoadLibrary, שניהם עושים את אותה פעולה, פשוט MustLoadDLL מעיף שגיאה אם לא מוצא את הdll.
מצורף קוד מלא של הפוסט:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
package main import ( "fmt" "strconv" "syscall" "unsafe" ) func GetLogicalDrives() []string { kernel32 := syscall.MustLoadDLL("kernel32.dll") GetLogicalDrives := kernel32.MustFindProc("GetLogicalDrives") n, _, _ := GetLogicalDrives.Call() s := strconv.FormatInt(int64(n), 2) var drives_all = []string{"A:", "B:", "C:", "D:", "E:", "F:", "G:", "H:", "I:", "J:", "K:", "L:", "M:", "N:", "O:", "P:", "Q:", "R:", "S:", "T:", "U:", "V:", "W:", "X:", "Y:", "Z:"} temp := drives_all[0:len(s)] var d []string for i, v := range s { if v == 49 { l := len(s) - i - 1 d = append(d, temp[l]) } } var drives []string for i, v := range d { drives = append(drives[i:], append([]string{v}, drives[:i]...)...) } return drives } func main() { fmt.Println("Hello, 世界") DrivesList := GetLogicalDrives() kernel32, _ := syscall.LoadLibrary("kernel32.dll") defer syscall.FreeLibrary(kernel32) GetDiskFreeSpaceEx, _ := syscall.GetProcAddress(syscall.Handle(kernel32), "GetDiskFreeSpaceExW") for _, drive := range DrivesList { lpFreeBytesAvailable := int64(0) lpTotalNumberOfBytes := int64(0) lpTotalNumberOfFreeBytes := int64(0) _, _, _ = syscall.Syscall6(uintptr(GetDiskFreeSpaceEx), 4, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(drive))), uintptr(unsafe.Pointer(&lpFreeBytesAvailable)), uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)), uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)), 0, 0) fmt.Printf("Disk Name %s\n", drive) fmt.Printf("Available %dmb\n", lpFreeBytesAvailable/1024/1024.0) fmt.Printf("Total %dmb\n", lpTotalNumberOfBytes/1024/1024.0) fmt.Printf("Free %dmb\n", lpTotalNumberOfFreeBytes/1024/1024.0) } } |
כשמריצים את האפליקציה, מקבלים את המסך הבא
ניתן לראות שהקוד עובד
ניתן לראות שהוא מכליל את G ככונן, בדר”כ יש type ואז לא מקבלים תוצאות עם 0.
מקווה שהפוסט היה מעניין ואשמח לענות על שאלות