نوع rune في Go هو اسم مستعار لـ int32.
نظرًا لأن نوع int32 هذا هو النوع الأساسي، فإن نوع rune يحمل قيمة عدد صحيح موقّع بطول 32 بت.
ومع ذلك، وخلافًا لنوع int32، فإن القيمة العددية المخزّنة في نوع rune تمثّل محرفًا واحدًا من Unicode.
Unicode مجموعة شاملة تحتوي على ASCII وتمثّل المحارف عبر تخصيص رقم فريد لكل محرف. يُسمّى هذا الرقم الفريد نقطة ترميز Unicode. وتهدف Unicode إلى تمثيل محارف العالم كله، بما فيها مختلف الأبجديات والأرقام والرموز وحتى الإيموجي، في صورة نقاط ترميز Unicode.
في Go، يمثّل نوع rune نقطة ترميز Unicode واحدة.
يضم الجدول التالي أمثلة على محارف Unicode مع نقطة ترميز Unicode الخاصة بها وقيمتها العشرية:
| Unicode Character | Unicode Code Point | Decimal Value |
|---|---|---|
| 0 | U+0030 |
48 |
| A | U+0041 |
65 |
| a | U+0061 |
97 |
| ¿ | U+00BF |
191 |
| π | U+03C0 |
960 |
| 🧠 | U+1F9E0 |
129504 |
UTF-8 هو ترميز محارف متغيّر الطول يُستخدم لترميز كل نقطة ترميز Unicode في صورة 1 أو 2 أو 3 أو 4 بايت.
وبما أن نقطة ترميز Unicode يمكن ترميزها في 4 بايت كحد أقصى، يحتاج نوع rune إلى القدرة على تخزين ما يصل إلى 4 بايت من البيانات.
ولهذا فإن نوع rune اسم مستعار لـ int32، لأن نوع int32 قادر على تخزين ما يصل إلى 4 بايت من البيانات.
تُرمَّز ملفات الكود المصدري في Go باستخدام UTF-8.
rune
يُعلن عن المتغيرات من النوع rune بوضع محرف بين علامتي تنصيص مفردتين:
myRune := '¿'
بما أن rune مجرد اسم مستعار لـ int32، فإن طباعة نوع قيمة من النوع rune ستُظهر int32:
myRune := '¿'
fmt.Printf("myRune type: %T\n", myRune)
// Output: myRune type: int32
وبالمثل، فإن طباعة قيمة من النوع rune ستُظهر قيمتها العددية (العشرية):
myRune := '¿'
fmt.Printf("myRune value: %v\n", myRune)
// Output: myRune value: 191
لطباعة محرف Unicode الذي يمثّله نوع rune، استخدم محدد التنسيق %c:
myRune := '¿'
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿
لطباعة نقطة ترميز Unicode التي يمثّلها نوع rune، استخدم محدد التنسيق %U:
myRune := '¿'
fmt.Printf("myRune Unicode code point: %U\n", myRune)
// Output: myRune Unicode code point: U+00BF
إلى جانب تعريف قيمة من النوع rune بوضع المحرف بين علامتي تنصيص مفردتين، يمكنك أيضًا تحديد الرقم السداسي عشر أو العشري:
myRune := rune(0xbf)
myRune = 191
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿
rune والسلاسل النصيةالسلاسل النصية في Go مرمّزة باستخدام UTF-8، ما يعني أنها تحتوي على محارف Unicode. تُخزَّن المحارف داخل السلاسل النصية وتُرمَّز في 1 أو 2 أو 3 أو 4 بايت حسب محرف Unicode الذي تمثّله.
في Go، تُستخدم الشرائح لتمثيل المتتاليات، ويمكن المرور على هذه الشرائح باستخدام range.
عندما نمرّ على سلسلة نصية، يحوّل Go السلسلة النصية إلى متتالية من قيم rune، كل منها 4 بايت (تذكّر أن نوع rune اسم مستعار لـ int32!).
ورغم أن السلسلة النصية ليست إلا شريحة من البايتات، فإن الكلمة المفتاحية range تمرّ على قيم rune في السلسلة النصية، لا على بايتاتها.
في هذا المثال، يمثّل المتغير index فهرس البداية لمتتالية بايتات قيمة rune الحالية، ويمثّل المتغير char قيمة rune الحالية:
myString := "❗hello"
for index, char := range myString {
fmt.Printf("Index: %d\tCharacter: %c\t\tCode Point: %U\n", index, char, char)
}
// Output:
// Index: 0 Character: ❗ Code Point: U+2757
// Index: 3 Character: h Code Point: U+0068
// Index: 4 Character: e Code Point: U+0065
// Index: 5 Character: l Code Point: U+006C
// Index: 6 Character: l Code Point: U+006C
// Index: 7 Character: o Code Point: U+006F
بما أن قيم rune يمكن تخزينها في 1 أو 2 أو 3 أو 4 بايت، فقد لا يساوي طول السلسلة النصية دائمًا عدد المحارف فيها.
استخدم الدالة المدمجة len للحصول على طول سلسلة نصية بالبايتات، والدالة utf8.RuneCountInString للحصول على عدد قيم rune في سلسلة نصية:
import "unicode/utf8"
myString := "❗hello"
stringLength := len(myString)
numberOfRunes := utf8.RuneCountInString(myString)
fmt.Printf("myString - Length: %d - Runes: %d\n", stringLength, numberOfRunes)
// Output: myString - Length: 8 - Runes: 6
rune
يمكن تحويل شريحة من قيم rune إلى سلسلة نصية:
myRuneSlice := []rune{'e', 'x', 'e', 'r', 'c', 'i', 's', 'm'}
myString := string(myRuneSlice)
fmt.Println(myString)
// Output: exercism
وبالمثل، يمكن تحويل سلسلة نصية إلى شريحة من قيم rune.
تذكّر أنه بدون محددات التنسيق، تُظهر طباعة قيمة من النوع rune قيمتها العددية (العشرية):
myString := "exercism"
myRuneSlice := []rune(myString)
fmt.Println(myRuneSlice)
// Output: [101 120 101 114 99 105 115 109]