من عاشق زبان برنامهنویسی گو هستم، یا مانند آنچه که بعضی میگویند: گولنگ. گو یک زبان ساده و عالی است.
من برای اولین بار حدود ژانویه ۲۰۱۶ با گو کار کردم. در آن زمان من چندان در مورد گو فکر نمیکردم. در آن زمان من سعی میکردم مهارتهای برنامهنویسیام را بهتر کنم و گو را برای انجام یک پروژه انتخاب کردم.
حتی یک سال قبل هم گو یک چیز درخشان بود. وقتی با مفاهیم کلی گو آشنا شدم برنامهنویسی با گو برایم تبدیل به یک کار سرراست شد.
من یک تکه کد مهم برای شرکتی که در آن کار میکنم یعنی Visuallead نوشتم که هنوز به خوبی کار میکند بدون اینکه هیچگونه هزینه نگهداری به ما تحمیل کند.
اخیرا من دوباره با گو کار کردم و حس کردم بهتر است که طی یک مقاله دلایل اینکه عاشق گو هستم را بنویسم.
محیط GOPATH
این یکی از اولین چیزهایی است که وقتی شما میخواهید با گو شروع به برنامه نویسی کنید باید تنظیم کنید.
پوشه GOPATH خودتان را هر جای کامپیوتر که میخواهید بسازید و در داخل آن پوشههای bin، src و pkg را بسازید. حالا شما آماده نوشتن کد هستید.
// How the directory structure looks like:
go
- bin
- pkg
- src
من در پوشه خانه خودم برای هر زبان برنامهنویسی که با آن کار میکنم یک پوشه ساختهام. پوشه خانه من پر از پوشههایی شبیه اینها است:
chef
cpp
elixir
elm
go
javascript
meteor
ocaml
php
python
scal
هیچکدام از این زبانها غیر از گو همچین ساختار پوشهای را تحمیل نمیکند. گو شما را مجبور میکند که یک پوشه ریشه برای تمام فایل های پروژه بسازید. این کار دلایل خوبی دارد که در ادامه این مقاله گفته میشود.
برنامه نوشته شده با گو
آیا میخواهید که با گو یک برنامه جدید بسازید؟ این کار آسان است. به مسیر پوشه GOPATH/src بروید، یک پوشه جدید بسازید، یک فایل جدید به نام file.go بسازید، فایل را در ویرایشگر باز کنید، پکیج را main بنامید، یک تابع جدید به نام {} ()func main بنویسید، و کار تمام است. از این لحظه به بعد همه امکانات گو در اختیار شماست.
ما بعداً در مورد امکانات گو حرف خواهیم زد اما اول اجازه دهید که در مورد ماژولهای گو حرف بزنیم.
ماژولهای گو
من سیستم ماژولها را در گو به عنوان یک جایگزین برای سیستم کلاسها در شیگرایی میبینم. زبان گو ماژولهایش را پکیج مینامد، در نتیجه از الان به بعد هر وقت ما از پکیج نام بردیم منظورمان ماژول است و برعکس.
Module == Package == Module
در زبان گو هر پوشهای که میسازید تبدیل به یک پکیج میشود. یک پکیج میتواند تبدیل به یک برنامه شود اگر اسمش main باشد. این کمک میکند که با استفاده از جداسازی طبیعی، قطعات کد را از لحاظ منطقی مدیریت کنیم.
در برنامه اخیرم من باید چند خط کد را در چند فایل دستکاری میکردم و بعد از تمام شدن کارم آنها را به AWS S3 آپلود میکردم. ساختار برنامه من اینجوری بود:
src
- my_app
- - main.go
- - main_test.go
- - uploader
- - - uploader.go
- - - uploader_test.go
- - replace_file_lines
- - - replace.go
- - - replace_test.go
- - - strings_util.go
- - - strings_util_test.go
فایلهای test.go_ برای اجرای یونیت تست در زبان گو استفاده می شوند. زبان گو یک فریمورک تست در هسته خودش دارد.
همچنین برای کسانی که از دنیای زبانهای شیگرا آمدهاند این ساختار کمک میکند که فکر کنیم که هر پوشه یک کلاس استاتیک کامل است، و هر متغیر و هر تابع در داخل فایلهای go. یک خصیصه یا متد است. در زیر مثالی از فایل replace.go را می بینید:
package replace_file_lines
import (
// ...
)
// Variables that begin with an uppercase is exposed
var PublicVariable int = 42
// While those that begin with loweracse are private to the module
var privateVariable int = 0
// Function that begins with an uppercase is exposed
func Replace(oldFilePath, outputFilePath, with, what string) {
// ...
}
// Function that begins with an uppercase is exposed
func PublicFunction(/* .. */) {
// ...
)
// While lowercase names makes functions private to the module
func privateFunction(/* .. */) {
// ...
)
اگر در هر پوشه بیشتر از یک فایل go. وجود داشته باشد همه ی متغیرها و متدها در سرتاسر پکیج به اشتراک گذاشته میشوند، حتی آنهایی که خصوصی هستند. این کار کمک میکند که یک پکیج را به قسمتهای کوچکتر تقسیم کنیم و مجبور نباشیم یک تکفایل بزرگ داشته باشیم.
بدون اینکه به دعوای شیگرایی در مقابل برنامهنویسی تابعی و رویهای بپردازیم، اینجا مهم است که بدانیم که طراحان زبان گو تصمیم گرفتند که شکل کلاسیک کلاسها را در زبان گو پیادهسازی نکنند و بجای آن از structها و اینترفیسها و البته پکیجها استفاده کنند.
برنامه gofmt
زبان گو برای اینکه متن کدها چه شکلی باشد قراردادهای مخصوص به خودش را دارد. یعنی شکل نوشتار هر خط از کد از قبل تعیین شده است. قالببندی سورسکدهای نوشته شده به زبان گو توسط برنامه gofmt انجام میگیرد. این به توسعهدهندگان اجازه میدهد که به جای اینکه بر سر مکان کروشهها با هم بحث کنند، روی نوشتن کد تمرکز کنند.
دعوای قدیمی بر سر مکان کروشهها:
برای کسب اطلاعات بیشتر به این لینک مراجعه کنید.
ساز و کار import در زبان گو
ایمپورتها در زبان گو همیشه نسبت به مسیر GOPATH/src سنجیده میشوند. من نمیتوانم بگویم که این تصمیم چقدر مرا از سردرگمی نجات داده است.
وقتی که شما با دیگر زبانها کار میکنید شما میتوانید در ایمپورتها هم از مسیرهای نسبی استفاده کنید و هم مسیرهای مطلق. یا حتی یک ایمپورت عجیب را جوری تنظیم کنید که یک فایل را از جایی که هیچکس نمیداند کجاست ایمپورت کند ( دارم به تو نگاه میکنم پایتون!).
زبان گو این مشکل را با یک روش منحصر به فرد حل کرده است. همهی ایمپورتها، بدون توجه به اینکه در چه فایلی هستند، همیشه نسبت به مسیر GOPATH/src سنجیده میشوند. در نتیجه در برنامه من ایمپورتهای فایل main این شکلی میشوند:
package main
import (
"my_app/replace_file_lines"
"my_app/uploader"
// ...
)
پوشه my_app در پوشه src قرار دارد، در نتیجه ما باید ابتدا آن را ذکر کنیم سپس پکیجهایی که در پوشه my_app هستند مثل replace_file_lines و uploader را ایمپورت میکنیم. دقت کنید که ما تکفایلها را ایمپورت نکردهایم بلکه همهی پکیج را ایمپورت کردهایم. این بسیار عالی کار میکند و باعث هیچگونه سردرگمی نمیشود.
علاوه بر این، گولنگ کامپایل نمیشود تا زمانی که شما از تمام پکیجهایی که ایمپورت کردهاید استفاده کنید. این ویژگی کمک میکند که بفهمید که همهی پکیجهای ایمپورت شده واقعا استفاده شدهاند.
سیستم دریافت پکیجها در گولنگ
بخش ایمپورت ما را به ویژگی جالب بعدی زبان گو راهنمایی میکند: ویژگی go get . در حالی که دیگر زبانها از سیستم مدیریت بسته npm متعلق به جاوا اسکریپت تاثیر گرفتهاند، زبان گو از مخازن گیت (git) به عنوان مدیریت بسته استفاده میکند.
این چگونه کار میکند؟
من قبلا در این مقاله در مورد آپلود به s3 نوشتهام، برای انجام این کار من به AWS SDK نیاز دارم. برای دریافت AWS SDK کافی است که ترمینال را باز کنم و دستور زیر را تایپ کنم:
go get github.com/aws/aws-sdk-go
در اینجا چه اتفاقی میافتد؟ اتفاق خاصی نمیافتد، گولنگ مخزن را از لینک https://github.com/aws/aws-sdk-go دانلود میکند و در پوشه GOPATH/src میریزد. بعد از این کار همه آنچه که برای استفاده ازaws-sdk نیاز دارید این است که آن را ایمپورت کنید:
package uploader
import (
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/aws"
// ...
)
آیا به خاطر میآورید که همهی ایمپورتها نسبت به مسیر GOPATH/src سنجیده میشوند؟ از آنجا میتوانید متوجه شوید که برای مثال پکیج s3 حالا در مسیرGOPATH/src/github.com/aws/aws-sdk-go/services/s3 قرار دارد.
سیستم بسته بندی و ساخت گولنگ
ما تا اینجا بر روی پوشه GOPATH/src تمرکز کرده بودیم، اما حالا وقتش رسیده است که به پوشههای دیگر یعنی GOPATH/pkg و GOPATH/bin بپردازیم.
گولنگ یک زبان کامپایلری است یعنی کد قبل از اجرا باید کامپایل شود. سرعت کامپایل گولنگ بالا ست، اما گولنگ چگونه این کار را انجام میدهد؟
هر بار که شما کد را برای اجرا کامپایل میکنید گولنگ یک فایل a. در پوشه GOPATH/pkg در همان مسیری که پکیج شما قرار دارد میسازد. این بدان معنی است که به عنوان مثال اگر شما aws-sdk را کامپایل کنید، این پکیج یک بار کامپایل میشود و بین همهی قسمتهای دیگر کد به اشتراک گذاشته میشود.
البته این تنها دلیل اینکه گولنگ خیلی سریع کامپایل میشود نیست. اما این یک خلاصه بود که به شما کمک کند که نقش پوشه GOPATH/pkg را درک کنید.
نقش پوشه GOPATH/bin چیست؟ وقتی که شما دستور go install را اجرا میکنید گولنگ یک فایل باینری میسازد و آن را در پوشه GOPATH/bin قرار میدهد. این فایل باینری نامش را از پوشه پکیج اصلی میگیرد ( در مثال ما my-app ).
چرا این اینقدر عالی است؟ چون شما میتوانید GOPATH/bin را به مسیر اصلی سیستمعامل خودتان اضافه کنید و همهی فایلهای اجرایی که شما میسازید از طریق خط فرمان در دسترس هستند.
سیستم ساخت چند-پلتفرمه گولنگ
آيآ میخواهید برای سیستمعاملی غیر از سیستمعاملی هماکنون در آن کدنویسی میکنید فایل اجرایی بسازید؟ خب نگران نباشید، شما برای اینکه برای ویندوز فایل بسازید به یک سیستم ویندوزی احتیاج ندارید. گولنگ نیاز شما را پوشش میدهد.
فقط کافی است دستور زیر را در ترمینال اجرا کنید:
GOOS=windows GOARCH=amd64 go install
گولنگ یک فایل اجرایی آماده به کار در ماشین ویندوزی را تولید میکند. فایل exe. در مسیر GOPATH/bin/windows_amd64/my_app.exe قرار میگیرد. مثل آب خوردن!
زبان گولنگ
هدف گولنگ این است که یک زبان ساده باشد.
من این پست را که پرسیده است چرا گولنگ طراحی نشده است که یک زبان فانکشنال باشد را دوست دارم. برنامهنویسهایی که در گوگل کار میکنند در اوایل کارشان هستند و بیشتر با زبانهای رویهای به خصوص زبان C آشنایی دارند. به این دلیل که لازم است برنامهنویسان در زبان جدید خیلی سریع به بازدهی برسند در نتیجه زبان برنامهنویسی جدید نمیتواند خیلی افراطی باشد.
این لیست چیزهایی است که گولنگ پشتیبانی نمیکند:
اگر چه بعضی وقت ها که با گو کد میزنم احساس کمبود بعضی از ویژگیها را میکنم ولی من میتوانم هر کاری میخواهم انجام دهم. این فقط نیاز دارد که بعضی وقتها کد بیشتری بنویسم یا بیشتر فکر کنم. مزیت این سادگی این است که کار کردن با کد ما راحتتر میشود زیرا کمتر انتزاعی است.
بعضی وقتها گو من را شگفتزده میکند وقتی بدون سالها تجربه کد نوشتن خیلی سریع به هدفم میرسم، فقط به خاطر اینکه این زیان خوشدست و واضح است.
همزمانی در گولنگ
من صحبت در مورد همزمانی (concurrency) را عمداً برای قسمت آخر مقاله گذاشتم. برای اینکه فکر میکنم این موضوع آنقدرها هم مهم نیست.
این یک ویژگی جالب از زبان است، اما بعضی وقتها این ویژگی به عنوان ماهیت اصلی گولنگ ذکر می شود، که من با آن موافق نیستم. درنتیجه اجازه دهید که من آن را در یک پاراگراف خلاصه کنم.
بله، گولنگ یک سیستم همزمانی عالی دارد. شما با تِرِدها روبرو نمیشوید تا اینکه گو-روتینها را بسازید که ساخت و مدیریتشان راحت است. گو-روتینها اجازه میدهند که بار برنامه را بین هستههای پردازنده توزیع کنید بدون اینکه در مورد مدیریت این کار نگران باشید.
اگر علاقه مند به خواندن بیشتر در مورد گو-روتین ها هستید این لینک را دنبال کنید.
منبع: hackernoon.com
این مطلب همچنین در این لینک در وبسایت شخصی من انتشار یافته است.