مسیرها
/
Go
Go
/
تمرین‌ها
/
لاگ‌ها، لاگ‌ها، لاگ‌ها!
لاگ‌ها، لاگ‌ها، لاگ‌ها!

لاگ‌ها، لاگ‌ها، لاگ‌ها!

تمرین یادگیری

مقدمه

نوع rune در Go نام دیگری برای 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

UTF-8 یک کدبندی کاراکتر با عرض متغیر است که برای کدبندی هر نقطه‌ی کد یونیکد به صورت ۱، ۲، ۳ یا ۴ بایت استفاده می‌شود. از آنجایی که یک نقطه‌ی کد یونیکد می‌تواند حداکثر به ۴ بایت کدبندی شود، نوع rune باید بتواند تا ۴ بایت داده را نگه دارد. به همین دلیل است که نوع rune نام دیگری برای int32 است، زیرا نوع int32 قادر است تا ۴ بایت داده را نگه دارد.

فایل‌های کد منبع 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

برای چاپ کاراکتر یونیکد نمایش‌داده‌شده توسط 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ها و رشته‌ها

رشته‌ها در 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 برای گرفتن طول یک رشته بر حسب بایت و از تابع 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

دستورالعمل‌ها

به شما سپرده شده است که یک کتابخانه‌ی لاگ بسازید تا در مدیریت لاگ‌های سازمانتان کمک کند. این کتابخانه به کاربران امکان می‌دهد تشخیص دهند کدام برنامه یک لاگ مشخص را تولید کرده است، لاگ‌های خراب را اصلاح کنند و تعیین کنند که آیا یک خط لاگ مشخص در محدوده‌ی تعداد کاراکتر معینی قرار دارد یا نه.

1. مشخص کنید کدام برنامه یک لاگ را تولید کرده است

لاگ‌ها از چندین برنامه می‌آیند که هر کدام از قالب لاگ اختصاصی خودش استفاده می‌کند. پیش از آنکه یک لاگ در سیستم تجمیع لاگ ذخیره شود، باید برنامه‌ای که آن را تولید کرده است مشخص شود.

تابع Application را پیاده‌سازی کنید که یک خط لاگ را می‌گیرد و برنامه‌ای را برمی‌گرداند که آن خط لاگ را تولید کرده است.

برای تشخیص اینکه کدام برنامه یک خط لاگ مشخص را تولید کرده است، خط لاگ را برای یافتن کاراکتر مشخصی که در جدول زیر آمده است جست‌وجو کنید:

برنامه کاراکتر نقطه‌ی کد یونیکد
recommendation ❗ U+2757
search 🔍 U+1F50D
weather ☀ U+2600

اگر یک خط لاگ هیچ‌کدام از کاراکترهای جدول بالا را نداشته باشد، مقدار default را به فراخوانی‌کننده برگردانید. اگر یک خط لاگ بیش از یک کاراکتر از جدول بالا داشته باشد، برنامه‌ای را برگردانید که با نخستین کاراکتر یافت‌شده در خط لاگ، از چپ به راست، متناظر است.

Application("❗ recommended search product 🔍")
// => recommendation

2. لاگ‌های خراب را اصلاح کنید

به دلیل یک باگ نادر اما پایدار در زیرساخت لاگ‌گیری، برخی کاراکترها در لاگ‌ها می‌توانند خراب شوند. پس از آنکه زمانی را صرف شناسایی کاراکترهای خراب و مقدار اصلی آن‌ها کردید، تصمیم می‌گیرید کتابخانه‌ی لاگ را به‌روزرسانی کنید تا در اصلاح لاگ‌های خراب کمک کند.

تابع Replace را پیاده‌سازی کنید که یک خط لاگ، یک کاراکتر خراب و مقدار اصلی را می‌گیرد و یک خط لاگ تغییر‌یافته را برمی‌گرداند که در آن همه‌ی موارد وقوع کاراکتر خراب با مقدار اصلی جایگزین شده‌اند.

log := "please replace '👎' with '👍'"

Replace(log, '👎', '👍')
// => please replace '👍' with '👍'"

3. تعیین کنید که آیا یک لاگ قابل نمایش است

سیستم‌هایی که مسئول نمایش لاگ‌ها هستند، محدودیتی روی تعداد کاراکترهایی دارند که می‌توان در هر خط لاگ نمایش داد. به همین دلیل، کاربران می‌خواهند این کتابخانه یک تابع کمکی داشته باشد تا تعیین کند آیا یک خط لاگ در محدوده‌ی تعداد کاراکتر مشخصی قرار دارد یا نه.

تابع WithinLimit را پیاده‌سازی کنید که یک خط لاگ و سقف کاراکتر را می‌گیرد و برمی‌گرداند که آیا خط لاگ در محدوده‌ی سقف کاراکتر قرار دارد یا نه.

WithinLimit("hello❗", 6)
// => true
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Go Exercism

آماده‌اید لاگ‌ها، لاگ‌ها، لاگ‌ها! را شروع کنید؟

در Exercism ثبت‌نام کنید تا Go را همراه با 34 مفهوم165 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.