Strings Under the Hood
Go string — bu baytlar to'plami. ASCII matn uchun buni sezmaysiz, lekin ingliz bo'lmagan belgilar va emoji bu farqni ochiqchasiga ko'rsatadi.
Stringlar — baytlar
s := "世界"
fmt.Println(len(s)) // 6, 2 emaslen() baytlarni sanaydi. UTF-8 世 ni 3 bayt, 界 ni 3 bayt sifatida kodlaydi, shuning uchun len("世界") — 6.
Indekslashda ham xuddi shu muammo bor:
s := "世界"
fmt.Println(s[0]) // 228s[0] bitta byte qaytaradi. "Hello" uchun bu tasodifan belgiga mos keladi. "世界" uchun esa bu ko'p baytli runening ma'nosiz bo'lagidir.
Range runelarni dekodlaydi
String ustidan range har bir iteratsiyada bitta rune beradi, o'sha rune nechta bayt egallashidan qat'i nazar:
for i, ch := range "世界" {
fmt.Printf("%d: %c\n", i, ch)
}
// 0: 世
// 3: 界Indeks 0 dan 3 ga sakraydi, chunki range 世 ning qolgan baytlarini o'tkazib yubordi. Siz bayt bo'laklarini emas, belgilarni olasiz.
Runelar — butun sonlar
rune shunchaki int32, shuning uchun runelarni butun son operatorlari bilan solishtirishingiz mumkin:
for _, ch := range s {
if ch >= 'a' && ch <= 'z' {
// kichik harf
}
}'a' va 'z' kabi belgi literallari butun son konstantalari, shuning uchun solishtirish oddiy sonli diapazon tekshiruvidir. Xuddi shu andaza katta harflar, raqamlar, yoki istalgan uzluksiz kod nuqtalari oralig'i uchun ishlaydi.
unicode/utf8 dagi yordamchilar
To'liq sikl kerak bo'lmaganda, unicode/utf8 tayyor yordamchilarga ega.
Belgilarni sanash:
import "unicode/utf8"
utf8.RuneCountInString("世界") // 2RuneCountInString stringda nechta rune borligini qaytaradi, buni len() ayta olmaydi.
Birinchi runeni dekodlash:
r, size := utf8.DecodeRuneInString("世界")
fmt.Println(r, size) // 19990 3
fmt.Println(string(r), size) // 世 3DecodeRuneInString ikkita qiymat qaytaradi:
- •
r: birinchi rune,int32kod nuqtasi sifatida - •
size: o'sha rune asl stringda nechta bayt egallagani
r butun son bo'lgani uchun, uni to'g'ridan-to'g'ri chop etish sizga 19990 kod nuqtasini beradi. Uni o'qiladigan belgiga qaytarish uchun string(r) dan foydalaning.
Bitta tuzoq: bo'sh stringda, DecodeRuneInString nol yoki xato emas, Unicode almashtirish belgisini U+FFFD (�) qaytaradi. Har doim bo'sh kirishdan himoyalaning:
func firstRuneSize(s string) int {
if s == "" {
return 0
}
_, size := utf8.DecodeRuneInString(s)
return size
}Belgilarni xohlaganingizda shu yordamchilardan foydalaning. len() va s[i] ga faqat haqiqatan ham baytlarni xohlaganingizda murojaat qiling.
>_ Exercise
Stringning birinchi belgisini string sifatida qaytaradigan firstChar ni yozing. U istalgan kirish uchun, jumladan emoji va ingliz bo'lmagan matn uchun ham ishlashi kerak.
Misollar:
- •
firstChar("Hello")"H"qaytaradi - •
firstChar("世界")"世"qaytaradi - •
firstChar("🚀 launch")"🚀"qaytaradi - •
firstChar("")""qaytaradi
Qadamlar:
- •1. Agar string bo'sh bo'lsa, boshqa hech narsa qilmasdan
""qaytaring. Bo'sh stringni dekodlash""emas, almashtirish belgisi �ni beradi. - •2.
unicode/utf8dan yordamchi bilan birinchi runeni dekodlang (paketni import qilishni unutmang). - •3. Qaytarishdan oldin o'sha runeni stringga aylantiring.
Ikkita bayt tuzog'idan ehtiyot bo'ling:
- •
s[0]— bitta bayt, belgi emas, shuning uchun uni to'g'ridan-to'g'ristringsifatida qaytarib bo'lmaydi (bayt va string turli turlar). - •
string(s[0])"Hello"uchun kompilyatsiya bo'ladi va o'tadi, lekin u faqat o'sha bitta baytni aylantiradi, shuning uchun 世 yoki 🚀 kabi ko'p baytli belgini buzadi. Buning o'rniga runeni dekodlang.
Stuck? Reveal a hint to help you.
Key Takeaway
Key Takeaway:
Go'da stringlar belgilar emas, baytlar ketma-ketligidir. Qaysi API'ga murojaat qilishingiz sizga haqiqatan nima kerakligiga bog'liq:
- •Baytlar: o'lcham uchun
len(s), bitta bayt uchuns[i]. Faqat kirish ASCII ekanligini bilganingizda ishlating. - •Belgilar: son uchun
utf8.RuneCountInString(s), bir vaqtda bitta rune bo'ylab aylanish uchunrange. - •Bir vaqtda bitta belgi:
utf8.DecodeRuneInString(s)sizga birinchi rune va uning bayt kengligini beradi, shunday qilib stringni xavfsiz qadam-baqadam o'tishingiz mumkin.
rune shunchaki int32 kod nuqtasi. Uni chop etsa bo'ladigan belgiga qaytarish uchun string(r) ichiga o'rang.
NEXT UP
Format Like a Pro
$ go run main.go
Kodingizni ishga tushiring