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

قابلیت‌های نداشته، قابلیت اصلی زبان Go

در اجتماع برنامه نویسان Go ضرب المثل جالبی وجود دارد:

مهم ترین قابلیت Go این است که خیلی از قابلیت‌ها را ندارد!

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

این یعنی انتظار نداشته باشید که مانند زبان‌های دیگر، در هر نسخه جدیدی که از Go منتشر می‌شود با انبوهی از قابلیت‌های جدید مواجه شوید. این افراد از دنیای Unix و C آمده اند، آیا انتظار دیگری از آن‌ها داشتید؟

طراحان Go معتقدند که تمرکز برنامه نویسان باید به خود زبان باشد نه قابلیت‌هایی که هر از چند ماه به آن اضافه می‌شود! لازم به ذکر است که از نظر زیر ساختی هر روز بهینه سازی‌های زیادی در Go صورت می‌گیرد. یادتان باشد که Go یک زبان Native است. حتی کامپایلرهای زبان C بعد از گذشت 40 سال هنز در حال توسعه هستند.

لیستی از قابلیت‌هایی که در Go وجود ندارند:

دقت کنید که سازندگان Go از قصد این قابلیت‌ها را به زبان اضافه نکرده اند و دلایل مناسبی هم برای کارشان دارند. اصولا یا به جای آن‌ها روش‌های ساده تر و بهتری را ارائه کرده اند یا اینکه شویه برنامه نویسی در Go به طریقی است که به این قابلیت‌ها نیاز ندارد:

  • کلاس ها
  • وراثت
  • سازنده‌ها و مخرب‌ها (Constructors & Destructors)
  • محاسبات شاره گر‌ها (Pointer Arthmetic)
  • ارجاع this
  • تمپلت‌ها (Templates)
  • استثناها (Exceptions)
  • سربار گذاری متدها (Method Overloading)
  • سربار گذاری عملگر (Operator Overloading)
  • و چندین قابلیت ریز و درشت دیگر ...

نواقص زبان برنامه نویسی Go

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

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

نقص اول تفاوت سرعت Go با زبان C است! Go به علت داشتن سیستم Runtime و سیستم Garbage Collector، حداقل به صورت تئوری هیچ وقت توانایی برابری با C را نخواهد داشت. اینکه چرا C تا این اندازه سریع است، خود نیاز به بحث جداگانه‌ای دارد.

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

فراموش نکنید که Go در حال حاضر هم یک زبان سریع محسوب می‌شود. اگر بخواهید Go را با زبان‌هایی مانند Python یا Ruby یا PHP و یا امثال آن‌ها مقایسه کنید، تجربه ثابت کرده است که Go بین 20 تا 50 برابر سریع تر عمل می‌کند.

البته موارد زیادی وجود دارد که دیده شده Go به نسبت این زبان‌ها کندتر عمل کند. در چنین حالتی، مطمئن باشید که آن عملیات در پشت صحنه توسط کدهای C اجرا شده است. در چنین زبان‌هایی برای حل مشکل سرعت، بسیار از ماژول‌ها را در C توسعه می‌دهند.

اگر بخواهیم Go را با زبان‌هایی مثل Java یا C# مقایسه کنیم، نمی‌توانیم با قطعیت نظری را مطرح نماییم. Microsoft و Oracle (همان SUN سابق) میزان زیادی از وقت و میلیون‌ها دلار از سرمایه خود را برای توسعه ماشین مجازی این دو زبان صرف کرده اند.

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

مطلب مهم این است که Go به شدت در حال توسعه است و تقریبا هر روز بهینه سازی‌های زیادی در آن اعمال می‌شود. حالا که Go به وضعیت ثبات رسیده است، تازه تیم توسعه کار خود را در زمینه بهینه سازی زبان شروع کرده. برای مثال تنها در یکی از بروز رسانی‌ها کدهای مربوط به Concurrent‌ها تا 50 درصد عمل کرد بهتری داشته اند.

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

نقص دیگر، سیستم Garbage Collector است. Go در ابتدا برای معماری x64 طراحی شده بود (64 بیت). دلیل آن هم این بود که چون پلتفرم‌های 32 بیتی کم کم در حال جایگزین شدن با پلتفرم‌های 64 بیتی هستند، تیم توسعه تمام توجه خود را به پلتفرم‌های 64 بیتی معطوف کرده بود.

متاسفانه در حاصر سیستم Garbage Collector روی معماری 32 بیت (x86) با یک نقص فنی روبرو است که در موارد معدودی می‌تواند باعث کرش کردن برنامه شود. البته این مشکل فقط برای معماری x86 است و اگر برنامه‌ها را روی معماری x64 اجرا کنید با مشکلی مواجه نخواهید شد. از همین رو توصیه شده است تا زمان برطرف کردن این مشکل، برنامه‌های خود را فقط روی سیستم‌های 64 بیتی اجرا کنید.

نکته بعدی این است که در حال حاضر سیستم Runtime روی پلتفرم‌های 64 بیتی، فقط توانایی استفاده از 16 گیگاایت حافظه دارد (به طور متوالی). خیلی نادر اند برنامه‌هایی که به صورت پیوسته به 16 گیگابایت حافظه نیاز داشته باشند، اما در صورت نیاز، باید برنامه خود را به قسمت‌های کوچکتری تقسیم کنید تا این محدودیت را دور بزنید.

در مخزن توسعه Go، اصلاحیه‌هایی بای رفع مشکل GC در سیستم‌های 32 بیتی وجود دارد، و میزان کسترش حافظه برای سیستم Runtime نیز به 128 گیگابایت افزایش داده شده است. به احتمال بسیار زیاد این اصلاحیه‌ها در نسخه 1.1 زبان قرار خواهند گرفت.

مشکل دیگری که در مورد این زبان وجود دارد نام این زبان است. اگر نام Go را در اینترنت جستجو کنید شاید به نتیجه دلخواه خود نرسید. به همین دلیل طبق قانونی که بین کاربران وجود دارد این زبان را نام Golang صدا می‌کنند، و تلفظ آن نیز مانند Erlang است.

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

در زبان‌هایی مثل Go یا C، تا زمانی که کاملا با طرز کار CPU، حافظه، I/O و مباحث سطح پایین مربوط به هر کدام آشنا نباشید، نمی‌توانید براحتی با زبان ارتباط برقرار کنید. شاید بتوانید به سادگی زبان آن را براحتی یاد بگیرید، اما آگاهی شما از زبان همیشه در حد پایینی قرار خواهد داشت. در حالی که یک برنامه نویس Ruby ممکن است هیچ وقت نیاز نداشته باشد تا از Register‌ها سر در بیاورد.

خصوصا برای استفاده از قابلیت‌های Concurency باید از پیش زمینه مناسبی برخوردار باشید. اینطور نیست که به صرف برنامه نویسی در این زبان، اطمینان پیدا کنید که برنامه شما روی یک CPU شانزده هسته‌ای شانزده برابر سریع تر اجرا خواهد شد! برنامه نویسی Concurrent نیازمند مطاعه زیاد و تجربه کافی است. Go برای شما معجزه نمی‌کند.

مباحث دیگری هم هستند که به اجتماع کاربران Go مربوط می‌شوند. تفکراتی در این اجتماع وجود دارد که ممکن است برای برنامه نویسانی که از زبان‌های دیگر می‌آیند کمی عجیب باشد.

برای مثال، تیم توسعه Go و اجتماع کاربری آن همیشه عنوان کرده اند که استفاده از کتابخانه‌های ساده، از اولیت بسیار بالاتری نسبت به فریم ورک‌ها برخوردار است؛ و این که فریم ورک‌ها یکی از عوامل اصلی در پیچیده شدن پروژه می‌باشند و هر چه کمتر از آن‌ها استفاده کنید بهتر است! و یا این که Andrew Gerrand یکی از اعضای اصلی تیم توسعه در اکانت تویتر خود اعلام می‌کند چقدر از این که Go فریم ورک‌هایی مثل Django یا Rails ندارد خوشحال است و امیدوار است که هیچ وقت هم نداشته باشد!

مسلماٌ برای خیلی از برنامه نویسان زبان‌های دیگر که به کار با فریم ورک‌ها عادت کرده اند چنین نظراتی کمی عجیب و غریب است! در Go فلسفه Unix حکم فرما است. جای تعجبی هم ندارد، چون این افراد خودشان خالق Unix هستند!

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

خیلی از برنامه نویسان تازه وارد متوجه نمی‌شند که چرا GO کار با Type و توابع را جایگزین Class‌ها و متدها کرده... چرا وراثت را از زبان حذف کرده... چرا این زبان Exception ندارد... چرا از سربار گذاری توابع پشتیبانی نمی‌کند... و ده‌ها سوال دیگر...

اما تقریبا اکثر آن‌ها بعد از مدتی که با Go کار کرده اند، عنوان کرده اند که‌ای کاش زبان پیشین آن‌ها مانند Go پیاده سازی شده بود! برنامه نویسان نباید در Go به شیوه Java کدنویسی کنند.... نباید به شیوه Python کدنویسی کنند... و یا هر زبان دیگری... و به صورت خلاصه باید گفت که در Go باید به شیوه Go برنامه نویسی کرد.

تگ ها: golang