جمعیت خرگوش‌ها


  • محدودیت زمان: ۱ ثانیه
  • محدودیت حافظه: ۲۵۶ مگابایت

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

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

Zootopia

ورودی🔗

در اولین خط ورودی، تعداد اولیه خرگوش‌ها (PP) و تعداد خرگوش‌هایی که هرساله توسط روباه خورده می‌شوند (LL) با یک فاصله داده می‌شود.

در خط دوم ورودی، انتهای سالی که جمعیت خرگوش‌ها پس از آن مدنظر است می‌آید. (YY)

1P,L,Y101 \le P, L, Y \le 10

تضمین می‌شود که در پایان سال اول، روباه همه‌ی خرگوش‌ها را نمی‌خورد.

L<2×P L \lt 2 \times P

همچنین تعداد خرگوش‌ها در هیچ زمانی صفر یا منفی نمی‌شود.

خروجی🔗

در تنها خط خروجی، تعداد خرگوش‌هایی که در آخر سال YY ام زنده هستند را چاپ کنید.

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

مثال🔗

ورودی نمونه ۱🔗

5 2
1
Plain text

خروجی نمونه ۱🔗

8
Plain text

در اینجا ۵ خرگوش اولیه داریم که در پایان سال به ۱۰ تا می‌رسد، سپس روباه ۲ تا از آن‌ها را می‌خورد. در پایان ۱ سال، ۸ خرگوش باقی‌مانده داریم.

ورودی نمونه ۲🔗

3 1
4
Plain text

خروجی نمونه ۲🔗

33
Plain text
  • ۳ خرگوش در پایان سال اول به ۵ خرگوش می‌رسند.

  • در پایان سال دوم به ۹ خرگوش می‌رسند.

  • در پایان سال سوم به ۱۷ خرگوش می‌رسند.

  • در نهایت در پایان سال چهارم به ۳۳ خرگوش می‌رسند.

کیبورد خراب


تیم کدکاپ برای تهیه کیبورد‌های مرحله‌ی حضوری کدکاپ به مشکل برخورد کرده است. قضیه از این قرار است که این کیبورد‌ها بسیار بی‌کیفیت هستند و کلید‌هایشان زود خراب می‌شود. بعد از اینکه یک کلید خراب می‌شود با فشار دادن آن هیچ اتفاقی نمی‌افتد.

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

یعنی در این کیبورد به ازای متن ورودی زیر:

Welcome to CodeCup7
Plain text

متن زیر را دریافت می‌کنید:

Welcome to Cdup7
Plain text

در اینجا چند تا از حروف خراب شدند؛ مثلاً o خراب شد و دیگر کار نکرد.

حال در این مسئله از شما می‌خواهیم که با داشتن «عدد کیفیت» یک کیبورد، مشخص کنید اگر کاربر بخواد با آن یک متن اولیه را وارد کنید به جایش چه متنی وارد می‌شود.

توجه🔗

  • این کیبورد‌ها اصلا Caps Lock ندارند.
  • عجیب بودن این کیبورد‌ها به اینجا خلاصه نشده. آن‌ها فقط یک شیفت دارند.
  • کیبورد اساساً امکان نگه داشتن یک کلید را ندارد و مثلاً برای تایپ "aa" باید دوبار کلید a را فشرد.
  • کاربر اصلا هیچ اشتباه تایپی نمی‌کند و از backspace استفاده نمی‌کند.
  • این کیبورد‌ها keypad ندارند.

کیبورد

جزئیات پروژه🔗

پروژه‌ی اولیه را از این لینک دانلود کنید. ساختار فایل‌های پروژه به‌صورت زیر است:

Keyboard
├── go.mod
├── go.sum
├── main.go
└── main_sample_test.go
Plain text

در فایل main.go دو تابع تعریف شده‌اند که شما باید آن‌ها را کامل کنید:

تابع NewKeyboard🔗

این تابع قرار است یک شی از نوع Keyboard را مقداردهی کند و بازگرداند. ورودی این متد همان «عدد کیفیت» کیبورد است. ساختار داخلی Keyboard را نیز می‌توانید به دلخواه طراحی و استفاده کنید.

extensionFromNamemain.go

type Keyboard struct {
     // TODO
}

func NewKeyboard(dure int) *Keyboard {
    return &Keyboard{
        // TODO
    }
}
Go

تابع Enter🔗

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

دقت کنید که ممکن است برای یک کیبورد چندین بار عملیات تایپ انجام شود. همچنین ممکن است در طول تایپ یک کلمه یک کلید خراب شود و در ادامه‌ی کلمه خراب باشد.

extensionFromNamemain.go

func (keyboard *Keyboard) Enter(inp string) string {
    // TODO
    return ""
}
Go

برای سادگی فرض کنید ورودی inp فقط از کارکترهای زیر تشکیل شده است:

  • حروف کوچک و بزرگ انگلیسی
  • اعداد انگلیسی
  • فاصله معمولی
  • کارکترهای خاص مقابل: ?!'

آن‌چه باید آپلود کنید🔗

پس از پیاده‌سازی توابع خواسته شده، فایل main.go را آپلود کنید.

آواتار جهانی


Aang

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

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

جزئیات پروژه🔗

پروژه‌ی اولیه را از این لینک دانلود کنید. ساختار فایل‌های پروژه به‌صورت زیر است:

gravatar
├── handlers
│   └── gravatar.go
├── test
│   └── gravatar_sample_test.go
├── go.mod
├── go.sum
└── main.go
Plain text

برنامه را به‌گونه‌ای پیاده‌سازی کنید که همه‌ی تست‌های سؤال پاس شوند.

نکات🔗

  • برای اجرای تست‌ها، می‌توانید از دستور go test ./test/... استفاده کنید.
  • تست‌های اصلی سؤال دقیقاً همان تست‌هایی هستند که در پروژه‌ی اولیه موجود است.
  • امکان اعمال تغییر در همه‌ی فایل‌های برنامه (به‌جز تست‌ها) را دارید، اما مجاز به اضافه کردن فایل جدید نیستید.

آن‌چه باید آپلود کنید🔗

پس از پیاده‌سازی برنامه، محتویات دایرکتوری اصلی برنامه را زیپ کرده و ارسال کنید، به‌طوری که هنگام باز کردن فایل زیپ، فایل main.go (و سایر فایل‌ها، در صورت نیاز) دیده شود.

یادت هست؟


Do you remember?

چیزی که از شما در این سوال می‌خواهیم، یک حافظه‌ی نهان (Cache) از نوع کلید و مقداری است. این حافظه‌ی نهان، اطلاعات را داخل دیسک نگه‌داری نمی‌کند و از نوع «داخل حافظه‌ای» است.

تا این‌جا احتمالاً ذهن‌تان سمت Redis رفته است، اما این حافظه به شکل خاص برای زبان Go طراحی شده و از امکانات این زبان بهره می‌برد. به طور خاص برای اتصال از سمت کاربر به حافظه‌ی نهان از چنل‌ها استفاده می‌شود.

روال کار استفاده از حافظه‌ی نهان را می‌توان به این شکل خلاصه کرد:

  • یک کَش جدید ساخته می‌شود. این کش از کش‌های دیگر که تا الان ساخته شده‌اند مجزا است.
  • از کش درخواست یک اتصال جدید می‌شود. در نتیجه یک جفت چنل ارسال و دریافت برمی‌گردد.
  • با کمک اتصال خود می‌توانیم به کش دستور دهیم، مثلاً یک کلید و مقدار دهیم تا ذخیره شود.
  • با کمک همین اتصال یا اتصالات دیگر می‌توانیم با داشتن کلید خود، مقدار را به دست بیاوریم.

به جز Get و Set که قابلیت‌های اولیه‌ی یک حافظه‌ی نهان هستند، یک عملیات دیگر نیز تعریف می‌شود به نام SetWithRTL که در اینجا RTL مخفف Request to Live است. این عدد برای هر کلید تعریف می‌شود و به معنی تعداد درخواست‌های خواندن است که پس از ذخیره شدن مقدار آن کلید می‌توانیم انجام دهیم تا نهایتاً آن کلید حذف شود. برای نمونه اگر یک RTL برابر با ۳ داشته باشیم، چنین اتفاقی می‌تواند بیفتد: پس از ۳ بار خواندن، آن مقدار از حافظه حذف شده است، به‌گونه‌ای که اصلاً وجود نداشته.

client: Set my_key my_val 3
client: Get my_key
server: my_val
client: Get my_key
server: my_val
client: Get my_key
server: my_val
client: Get my_key
server: 
Plain text

جزئیات پروژه🔗

پروژه‌ی اولیه را از این لینک دانلود کنید. ساختار فایل‌های پروژه به صورت زیر است:

cache/
├── go.mod
├── go.sum
├── main.go
├── cache.go
└── main_sample_test.go
Plain text

در فایل cache.go چند تابع وجود دارد که در main.go استفاده شده‌اند و شما باید آن‌ها را کامل کنید.

در فایل main.go که نمی‌توانید محتوای آن را تغییر دهید، پیاده‌سازی سمت کاربر این حافظه‌ی نهان آمده است و در فایل تست نمونه، نحوه استفاده از آن آمده است.

در فایل cache.go فقط امضای توابع آمده‌اند. شما باید مطابق خواسته‌ی صورت سؤال توابع را کامل کرده و در صورت نیاز توابع جدید اضافه کنید.

فایل main.go‍🔗

extensionFromNamemain.go

func (conn *CacheClientConnection) Set(key string, val CacheVal) {
}

func (conn *CacheClientConnection) SetWithRTL(key string, val CacheVal, RTL int) {
}

func (conn *CacheClientConnection) Get(key string) CacheVal {
}
Go

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

فایل cache.go🔗

extensionFromNamecache.go
type Cache struct {
}

type CacheServerConnection struct {
}

func InitCache() *Cache {
    // TODO
    return nil
}

func (cache *Cache) Connect(name string) *CacheClientConnection {
}
Go

تابع InitCache🔗

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

تابع Connect🔗

در این قسمت یک کاربر جدید با یک نام جدید (که تضمین می‌شود یکتاست) می‌خواهد به این کش متصل شود. برای این منظور یک جفت چنل درست می‌شود که در قالب یک CacheClientConnection‍ به کاربر برمی‌گردد. همچنین باید این دو چنل برای خود کش نیز نگه داشته شوند تا بتوان به آن‌ها گوش داد.

آن‌چه باید آپلود کنید🔗

پس از پیاده‌سازی توابع خواسته‌شده، فایل cache.go را آپلود کنید.

جدول یا آبجکت؟


دیتابیس

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

جزئیات پروژه🔗

پروژه‌ی اولیه را از این لینک دانلود کنید. ساختار فایل‌های پروژه به‌صورت زیر است:

orm
├── test
│   └── orm_sample_test.go
├── configurators.go
├── driver.go
├── go.mod
├── go.sum
├── orm.go
└── query.go
Plain text

استراکت EntityConfigurator🔗

این استراکت در فایل configurators.go تعریف شده است. موجودیت‌های برنامه می‌توانند شامل اطلاعات مختفی نظیر نام جدول باشند. این اطلاعات می‌توانند در این استراکت ذخیره شوند. متدی با نام Table برای این نوع داده تعریف شده است که فیلد table (نام جدول) مربوط به موجودیت را مقداردهی می‌کند. در صورت نیاز، می‌توانید ساختار این استراکت را تغییر دهید، اما نباید امضای متد Table را تغییر دهید.

استراکت Driver🔗

قرار است ORM ما بتواند به دیتابیس‌های مختلف متصل شود. درایورها، جزئیات پیاده‌سازی مربوط به DBMS های مختلف را مشخص می‌کنند. استراکت Driver در فایل driver.go تعریف شده است. همچنین یک استراکت بدون نام در متغیر Drivers تعریف شده که شامل دو درایور در قالب فیلدهای PostgreSQL و SQLite3 است. نام درایور PostgreSQL را برابر با postgres و نام درایور SQLite3 را برابر با sqlite3 قرار دهید. یک فیلد با نام PlaceHolderGenerator نیز وجود دارد که مقدار آن یک تابع است که با دریافت تعداد پارامترهای موجود در یک کوئری SQL ، آرایه‌ای از رشته‌ها که بیانگر placeholder مقادیر موجود در کوئری هستند را برمی‌گرداند. این تابع را برای دو درایور تعریف‌شده به‌صورت زیر پیاده‌سازی کنید:

  • در درایور PostgreSQL، تابع PlaceHolderGenerator باید با دریافت n، مجموعه‌ای از رشته‌ها به فرم $i (به‌طوری که i از 1 تا n است) را برگرداند. برای مثال، اگر مقدار n برابر با 3 باشد، خروجی باید به‌ترتیب شامل رشته‌های $1، $2 و $3 باشد.
  • در درایور SQLite3، تابع PlaceHolderGenerator باید با دریافت n، یک آرایه از رشته‌ها به‌طول n که مقادیر آن همگی برابر با ? هستند برگرداند.

اینترفیس Entity🔗

این اینترفیس در فایل orm.go تعریف شده و شامل یک متد ConfigureEntity(e *EntityConfigurator) است. موجودیت‌های برنامه باید این اینترفیس را پیاده‌سازی کنند. متد ConfigureEntity این اینترفیس، پیکربندی اولیه‌ی یک Entity را انجام می‌دهد (مثلاً نگه‌داری نام جدول مربوط به موجودیت) که به ازای هر Entity توسط برنامه‌نویس آن پیاده‌سازی می‌شود.

استراکت ConnectionConfig🔗

این استراکت شامل پوینتری به یک sql.DB، پوینتری به یک درایور و آرایه‌ای از موجودیت‌های برنامه است. از این ConnectionConfigها در تابع SetupConnections استفاده می‌شود.

تابع SetupConnections🔗

این تابع با دریافت تعداد نامشخصی ConnectionConfig، اتصال مربوط به کانکشن‌ها را برقرار می‌کند و مقداردهی‌های اولیه‌ی لازم برای کانکشن‌ها را انجام می‌دهد.

تابع Find🔗

این تابع با دریافت کلید اصلی (عددی) یک موجودیت از نوع T (جنریک)، اطلاعات مربوط به سطر موردنظر از دیتابیس را باید در قالب یک آبجکت از نوع T برگرداند. نام ستون‌ها در جدول به‌صورت snake_case هستند، اما نام فیلدهای نوع داده‌ی T به‌صورت PascalCase است. برای مثال، اگر در یک موجودیت، فیلدی با نام BodyText داشته باشیم، در جدول متناظر با موجودیت، ستونی با نام body_text وجود خواهد داشت. تضمین می‌شود که فیلدها برای ستون‌های مختلف جدول تعریف شده‌اند.

تابع All🔗

این تابع، اطلاعات مربوط به سطرهای جدول موردنظر از دیتابیس (با توجه به نوع داده‌ی جنریک) را باید در قالب آرایه‌ای از Tها برگرداند.

تابع First🔗

این تابع باید اطلاعات اولین سطر (بر اساس کلید اصلی جدول) در جدول موردنظر (با توجه به نوع داده‌ی جنریک) را در قالب آبجکتی از نوع T برگرداند.

تابع Last🔗

این تابع باید اطلاعات آخرین سطر (بر اساس کلید اصلی جدول) در جدول موردنظر (با توجه به نوع داده‌ی جنریک) را در قالب آبجکتی از نوع T برگرداند.

استراکت QueryBuilder🔗

این استراکت شامل اطلاعات یک کوئری برای تبدیل به فرمت SQL است که در فایل query.go تعریف شده. آن را به دلخواه پیاده‌سازی کنید.

تابع NewQueryBuilder را به‌گونه‌ای پیاده‌سازی کنید که یک نمونه‌ی جدید از نوع QueryBuilder برگرداند.

متدهای زیر برای استراکت QueryBuilder تعریف شده که باید آن‌ها را پیاده‌سازی کنید:

  • متد Get: این متد باید کوئری مدنظر (با توجه به متدهای فراخوانی‌شده روی QueryBuilder) را اجرا کرده و نتیجه را در قالب یک آبجکت از نوع OUTPUT (به‌صورت جنریک) برگرداند. در این‌صورت، تنها اولین نتیجه برمی‌گردد.
  • متد All: این متد باید کوئری مدنظر (با توجه به متدهای فراخوانی‌شده روی QueryBuilder) را اجرا کرده و همه‌ی نتایج را در قالب آرایه‌ای از OUTPUTها (به‌صورت جنریک) برگرداند.
  • متد OrderBy: این متد با دریافت نام یک ستون و نحوه‌ی ترتیب (ASC یا DESC، به‌معنای صعودی یا نزولی) باید یک بخش ORDER BY به کوئری اضافه کند.
  • متد Where: این متد می‌تواند حداقل دو آرگومان دریافت کند:
    • اگر دو آرگومان به این متد پاس داده شود، اولین آرگومان نام یک ستون و دومین آرگومان مقدار مدنظر خواهد بود. شرط برابر بودن مقدار ستون موردنظر با مقدار واردشده باید به کوئری اضافه شود. در صورتی که شرطی از قبل به کوئری اضافه شده باشد، شرط فعلی باید با شرط‌های قبلی AND شود.
    • اگر سه آرگومان به این متد پاس داده شود، اولین آرگومان نام یک ستون، دومین آرگومان یک عملگر (نظیر =) و سومین آرگومان مقدار مدنظر خواهد بود. شرط واردشده باید به کوئری اضافه شود. در صورتی که شرطی از قبل به کوئری اضافه شده باشد، شرط فعلی باید با شرط‌های قبلی AND شود.
    • اگر بیش از سه آرگومان به این متد پاس داده شود و آرگومان دوم برابر با رشته‌ی IN باشد، آرگومان اول برابر با نام ستون موردنظر خواهد بود. آرگومان سوم به بعد، مقادیری هستند که مقدار ستون موردنظر باید حداقل برابر با یکی از آن‌ها باشد.
  • متد WhereIn: عملکرد این متد، مشابه حالت سوم متد Where است.
  • متد AndWhere: عملکرد این متد، مشابه متد Where است.
  • متد OrWhere: عملکرد این متد، مشابه متد Where است، با این تفاوت که اگر شرطی از قبل در کوئری موجود باشد، شرط جدید با شرط‌های قبلی OR خواهد شد.
  • متد Limit: این متد با دریافت یک عدد، limit موجود در کوئری را مشخص می‌کند.
  • متد Offset: این متد با دریافت یک عدد، offset موجود در کوئری را مشخص می‌کند.
  • متد Table: این متد با دریافت نام جدول در قالب یک رشته، نام جدولی که کوئری باید روی آن اجرا شود را مشخص می‌کند.
  • متد GroupBy: این متد با دریافت تعداد نامشخصی رشته، یک عبارت group by به کوئری اضافه می‌کند. در صورتی که این متد چند بار فراخوانی شود، ستون‌ها باید به‌ترتیب به بخش group by کوئری اضافه شوند.
  • متد Select: این متد با دریافت تعداد نامشخصی رشته، مشخص می‌کند که مقدار کدام ستون‌ها از جدول دیتابیس دریافت شوند. اگر این متد فراخوانی نشود، همه‌ی ستون‌ها (*) باید از جدول موجود در دیتابیس دریافت شوند. اگر این متد چند بار فراخوانی شود، ستون‌ها باید به‌ترتیب به کوئری اضافه شوند.
  • متد SetDriver: این متد با دریافت یک Driver، باید موارد موردنیاز برای کوئری بیلدر (نظیر PlaceHolderGenerator) را به موارد موجود در Driver تغییر دهد.
  • متد ToSql: این متد باید کوئری SQL تولیدشده را در قالب یک رشته و مقادیر پارامترهای موجود در کوئری را در قالب آرایه‌ای از interface{}ها برگرداند. اگر اولین فراخوانی روی یک آبجکت جدید QueryBuilder مربوط به متد ToSql بود، مقدار خروجی error را برابر با یک رشته‌ی غیر از خالی قرار دهید. در غیر این‌صورت، error را nil برگردانید.

نکته: در صورتی که چند شرط AND و OR شوند، صرفاً کافی است تا آن‌ها را با استفاده از عملگرهای مربوطه (بین پرانتز) کنار یکدیگر قرار دهید. مثال:

WHERE cond1 OR cond2 AND cond3 OR cond4
SQL

کوئری‌های تولیدشده توسط QueryBuilder باید مطابق با مثال‌های زیر باشند (فاصله و کوچکی و بزرگی حروف مهم است):

مثال ۱:🔗

s := orm.NewQueryBuilder[Dummy]()
s.Table("users")
s.ToSql()
Go

کوئری ایجادشده:

SELECT * FROM users
SQL

مثال ۲:🔗

s.Table("users").SetDriver(orm.Drivers.SQLite3).
    Where("age", 10).
    AndWhere("age", "<", 10).
    Where("name", "CodeCup").
    OrWhere("age", ">", 11)
    .ToSql()
Go

کوئری ایجادشده در درایور SQLite3:

SELECT * FROM users WHERE age = ? AND age < ? AND name = ? OR age > ?
SQL

مثال ۳:🔗

orm.NewQueryBuilder[Dummy]().
    SetDriver(orm.Drivers.PostgreSQL).
    Table("users").
    WhereIn("id", 1, 2, 3, 4, 5, 6).
    ToSql()
Go

کوئری ایجادشده در درایور PostgreSQL:

SELECT * FROM users WHERE id IN ($1, $2, $3, $4, $5, $6)
SQL

نکات🔗

  • توجه داشته باشید که در این ORM شما باید مستقیماً با دیتابیس در ارتباط باشید و امکان هندل کردن داده‌ها به‌صورت in-memory را ندارید.
  • در صورت نیاز، می‌توانید فایل‌های جدیدی در برنامه تعریف کنید، اما امکان ایجاد دایرکتوری جدید را ندارید.
  • می‌توانید از کتاب‌خانه‌های 3rd party در کد خود استفاده کنید. در این‌صورت، باید فایل‌های go.mod و go.sum را نیز در فایل زیپ ارسالی خود قرار دهید.

آن‌چه باید آپلود کنید🔗

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