Go-তে rune টাইপ হলো int32-এর একটি অ্যালিয়াস।
এই অন্তর্নিহিত int32 টাইপের কারণে rune টাইপ একটি সাইনযুক্ত ৩২-বিট ইন্টিজার মান ধারণ করে।
তবে int32 টাইপের বিপরীতে, rune টাইপে সংরক্ষিত ইন্টিজার মান একটি একক ইউনিকোড ক্যারেক্টার প্রকাশ করে।
ইউনিকোড হলো ASCII-এর একটি সুপারসেট, যা প্রতিটি ক্যারেক্টারকে একটি অনন্য সংখ্যা বরাদ্দ করে ক্যারেক্টারগুলো প্রকাশ করে। এই অনন্য সংখ্যাটিকে বলা হয় ইউনিকোড কোড পয়েন্ট। ইউনিকোডের লক্ষ্য হলো বিশ্বের সব ক্যারেক্টার, যার মধ্যে নানা বর্ণমালা, সংখ্যা, চিহ্ন এবং এমনকি ইমোজিও রয়েছে, ইউনিকোড কোড পয়েন্ট হিসেবে প্রকাশ করা।
Go-তে rune টাইপ একটি একক ইউনিকোড কোড পয়েন্ট প্রকাশ করে।
নিচের টেবিলে উদাহরণস্বরূপ কিছু ইউনিকোড ক্যারেক্টার এবং তাদের ইউনিকোড কোড পয়েন্ট ও দশমিক মান দেওয়া হলো:
| ইউনিকোড ক্যারেক্টার | ইউনিকোড কোড পয়েন্ট | দশমিক মান |
|---|---|---|
| 0 | U+0030 |
48 |
| A | U+0041 |
65 |
| a | U+0061 |
97 |
| ¿ | U+00BF |
191 |
| π | U+03C0 |
960 |
| 🧠 | U+1F9E0 |
129504 |
UTF-8 হলো একটি পরিবর্তনশীল-প্রস্থের ক্যারেক্টার এনকোডিং, যা প্রতিটি ইউনিকোড কোড পয়েন্টকে ১, ২, ৩ বা ৪ বাইট হিসেবে এনকোড করতে ব্যবহৃত হয়।
যেহেতু একটি ইউনিকোড কোড পয়েন্ট সর্বোচ্চ ৪ বাইটে এনকোড করা যায়, তাই rune টাইপকে ৪ বাইট পর্যন্ত ডেটা ধারণ করতে সক্ষম হতে হয়।
এ কারণেই rune টাইপ int32-এর একটি অ্যালিয়াস, কারণ একটি int32 টাইপ ৪ বাইট পর্যন্ত ডেটা ধারণ করতে পারে।
Go-এর সোর্স কোড ফাইল UTF-8 দিয়ে এনকোড করা হয়।
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
runeটি যে ইউনিকোড ক্যারেক্টার প্রকাশ করে তা প্রিন্ট করতে %c ফরম্যাটিং ভার্ব ব্যবহার করুন:
myRune := '¿'
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿
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: ¿
Go-তে স্ট্রিং UTF-8 দিয়ে এনকোড করা হয়, অর্থাৎ এগুলোতে ইউনিকোড ক্যারেক্টার থাকে। স্ট্রিংয়ের ক্যারেক্টারগুলো যে ইউনিকোড ক্যারেক্টার প্রকাশ করে তার উপর নির্ভর করে ১, ২, ৩ বা ৪ বাইট হিসেবে সংরক্ষণ ও এনকোড করা হয়।
Go-তে সিকোয়েন্স প্রকাশ করতে স্লাইস ব্যবহার করা হয় এবং range দিয়ে এই স্লাইসগুলোর উপর ইটারেশন করা যায়।
যখন আমরা একটি স্ট্রিংয়ের উপর ইটারেশন করি, Go স্ট্রিংটিকে একগুচ্ছ Rune-এ রূপান্তর করে, যার প্রতিটি ৪ বাইট (মনে রাখবেন, 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 ১, ২, ৩ বা ৪ বাইট হিসেবে সংরক্ষণ করা যায়, তাই একটি স্ট্রিংয়ের দৈর্ঘ্য সবসময় স্ট্রিংয়ের ক্যারেক্টার সংখ্যার সমান নাও হতে পারে।
বাইটে একটি স্ট্রিংয়ের দৈর্ঘ্য পেতে বিল্ট-ইন len ফাংশন এবং একটি স্ট্রিংয়ে Rune-এর সংখ্যা পেতে utf8.RuneCountInString ফাংশন ব্যবহার করুন:
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-এর একটি স্লাইসকে স্ট্রিং-এ টাইপ কনভার্ট করা যায়:
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]