مسیرها
/
Go
Go
/
تمرین‌ها
/
نیاز به سرعت
نیاز به سرعت

نیاز به سرعت

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

مقدمه

در Go، یک struct دنباله‌ای از عناصر نام‌دار است که به آن‌ها «فیلد» می‌گویند؛ هر فیلد یک اسم و یک نوع دارد. اسم هر فیلد باید درون struct یکتا باشد. می‌توان structها را با «کلاس‌ها» در الگوی برنامه‌نویسی شیءگرا مقایسه کرد.

تعریف struct

برای ساختن یک struct تازه، از «کلیدواژه»های type و struct استفاده می‌کنید و اسم و نوع فیلدها را به‌صراحت تعریف می‌کنید. برای مثال، اینجا structی به اسم Shape تعریف می‌کنیم که اسم یک شکل و اندازه‌اش را نگه می‌دارد:

type Shape struct {
    name string
    size int
}

اسم فیلدها در structها از قرارداد Go پیروی می‌کند: فیلدهایی که اسمشان با حرف کوچک شروع می‌شود، فقط برای کدهای همان بسته قابل مشاهده‌اند، در حالی که فیلدهایی که اسمشان با حرف بزرگ شروع می‌شود، در بسته‌های دیگر هم قابل مشاهده‌اند.

ساختن نمونه‌هایی از یک struct

پس از اینکه struct را تعریف کردید، باید یک نمونه‌ی تازه بسازید و فیلدها را با اسم فیلدشان و به هر ترتیبی که می‌خواهید تعریف کنید:

s := Shape {
    name: "Square",
    size: 25,
}

برای خواندن یا تغییر فیلدهای یک نمونه، از نشانه‌گذاری . استفاده کنید:

// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35

فیلدهایی که مقدار اولیه‌ای به آن‌ها اختصاص داده نشود، مقدار صفر خود را خواهند داشت. برای مثال:

s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0

می‌توانید بدون استفاده از اسم فیلدها هم نمونه‌ای از یک struct بسازید، به شرطی که فیلدها را به ترتیب تعریف کنید:

s := Shape {
	"Oval",
	20,
}

با این حال، این نحوه‌ی نگارش کد شکننده در نظر گرفته می‌شود، چون با اضافه شدن یک فیلد می‌تواند از کار بیفتد، به‌ویژه وقتی فیلد تازه از نوع دیگری باشد. در مثال زیر یک فیلد اضافه به Shape اضافه می‌کنیم:

type Shape struct {
	name        string
	description string // new field 'description' added
	size        int
}

s := Shape{
    "Circle",
    20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}

توابع «New»

گاهی داشتن توابعی که به ما در ساختن نمونه‌های struct کمک می‌کنند می‌تواند خوشایند باشد. طبق قرارداد، این توابع را معمولاً New می‌نامند یا اسمشان با New شروع می‌شود، اما چون فقط توابعی معمولی هستند، می‌توانید هر اسمی که می‌خواهید برایشان انتخاب کنید. ممکن است توابع سازنده در زبان‌های دیگر را به یادتان بیاورند، اما در Go فقط توابعی معمولی هستند.

در مثال زیر، یکی از این توابع New برای ساختن نمونه‌ی تازه‌ای از Shape استفاده می‌شود و به‌طور خودکار مقدار پیش‌فرضی برای size شکل تنظیم می‌کند:

func NewShape(name string) Shape {
	return Shape{
		name: name,
		size: 100, //default-value for size is 100
	}
}

NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }

استفاده از توابع New می‌تواند مزایای زیر را داشته باشد:

  • اعتبارسنجی مقادیر داده‌شده
  • مدیریت مقادیر پیش‌فرض
  • چون توابع New اغلب در همان بسته‌ی structهایی که مقداردهی اولیه می‌کنند تعریف می‌شوند، می‌توانند حتی فیلدهای خصوصی struct را هم مقداردهی اولیه کنند

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

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

خودروها با باتری کاملاً پر (۱۰۰٪) شروع می‌کنند. هر بار که خودرو را با کنترل از راه دور می‌رانید، به اندازه‌ی سرعت خودرو متر می‌پیماید و درصد باقی‌مانده‌ی باتری را به اندازه‌ی مصرف باتری‌اش کاهش می‌دهد.

اگر شارژ باتری خودرو کمتر از درصد مصرف باتری آن باشد، دیگر نمی‌توانید خودرو را برانید.

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

1. ساخت یک خودروی کنترلی

یک ساختار Car با فیلدهای زیر از نوع int تعریف کنید:

  • battery
  • batteryDrain
  • speed
  • distance

با تعریف تابع NewCar امکان ساخت یک خودروی کنترلی را فراهم کنید؛ این تابع سرعت خودرو بر حسب متر و درصد مصرف باتری را به عنوان دو پارامتر خود (هر دو از نوع int) می‌گیرد و یک نمونه Car برمی‌گرداند:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
// => Car{speed: 5, batteryDrain: 2, battery:100, distance: 0}

2. ساخت یک پیست مسابقه

یک ساختار دیگر به نام Track با فیلد distance از نوع عدد صحیح تعریف کنید. با تعریف تابع NewTrack امکان ساخت یک پیست مسابقه را فراهم کنید؛ این تابع مسافت پیست بر حسب متر را به عنوان تنها پارامتر خود (که از نوع int است) می‌گیرد:

distance := 800
track := NewTrack(distance)
// => Track{distance: 800}

3. راندن خودرو

تابع Drive را پیاده‌سازی کنید که تعداد مترهای پیموده‌شده را بر اساس سرعت خودرو به‌روزرسانی می‌کند و باتری را به اندازه‌ی مصرف باتری کاهش می‌دهد. اگر باتری برای یک بار رانندگی دیگر کافی نباشد، خودرو حرکت نمی‌کند:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
car = Drive(car)
// => Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5}

4. بررسی اینکه آیا یک خودروی کنترلی می‌تواند مسابقه را به پایان برساند

برای به پایان رساندن یک مسابقه، خودرو باید بتواند مسافت مسابقه را بپیماید. یعنی نباید باتری‌اش پیش از عبور از خط پایان خالی شود. تابع CanFinish را پیاده‌سازی کنید که یک نمونه Car و یک نمونه Track را به عنوان پارامترهایش می‌گیرد و اگر خودرو بتواند مسابقه را به پایان برساند true و در غیر این صورت false برمی‌گرداند.

فرض کنید هم‌اکنون در خط شروع مسابقه هستید و موتور خودرو را برای مسابقه روشن می‌کنید. در نظر بگیرید که ممکن است باتری خودرو هنگام شروع مسابقه لزوماً کاملاً شارژ نباشد:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)

distance := 100
track := NewTrack(distance)

CanFinish(car, track)
// => true
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Go Exercism

آماده‌اید نیاز به سرعت را شروع کنید؟

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