برنامه نویس فان | Fun Developer یک آدم ساده که عاشق برنامه نویسی و کد زدنه :) تلاش میکنه تا به بقیه کمک کنه. توسعه دهنده هسته لاراول و فضای اوپن سورس. فاندر پرانتز و کد نیوز.

کامپایلر دایرکیتو (Compiler Directives) چیه؟
دستورالعملهای کامپایلر، دستورات ویژهای هستند که در کامنتهای کد قرار میگیرند و معمولاً با //go:
شروع میشوند. این دستورات به کامپایلر یا ابزارهای مرتبط با Go نحوه پردازش کد را مشخص میکنند. از رایجترین این دستورالعملها میتوان به موارد زیر اشاره کرد:
-
//go:generate
برای مشخص کردن کدهای تولیدشده -
//go:build
برای تعیین شرایط ساخت کد -
//go:nolint
برای جلوگیری از بررسی کد توسط ابزار lint
دستورالعملهای گولنگ نوآوری جدیدی در این زبان نیستند، بلکه در زبانهای دیگر نیز وجود دارند، مانند #[inline(always)]
در Rust. در زبان Go، بهصورت پیشفرض inline فعال است، اما برای غیرفعال کردن آن میتوان از //go:noinline
استفاده کرد.
go:build
دستور //go:build
در نسخه Go 1.17 معرفی شد تا جایگزین //+build
شود. این دستور امکان کامپایل کد را بر اساس شرایط مختلفی مانند سیستمعامل، معماری پردازنده، نسخه Go و غیره فراهم میکند.
نحوه استفاده از //go:build
فرمت کلی این دستور بهصورت زیر است:
//go:build <عبارت شرطی>
در اینجا، عبارت شرطی تعیین میکند که کد تحت چه شرایطی کامپایل شود. برخی از نمونهها:
-
linux && amd64
→ کامپایل فقط روی سیستمعامل لینوکس با معماری amd64 -
!windows
→ کامپایل روی همه سیستمها بهجز ویندوز -
darwin || linux
→ کامپایل روی مک (darwin) یا لینوکس
سیستمعاملها و معماریهای متداول
-
سیستمعاملها:
linux
,windows
,darwin
,freebsd
,netbsd
,openbsd
-
معماریهای پردازنده:
amd64
,arm
,arm64
,386
,mips
ترکیب //go:build
با نام فایل
همچنین میتوان این دستور را همراه با نام فایل استفاده کرد. مثلاً، فایل main_linux.go
که همراه با //go:build linux
مشخص شده است، فقط روی لینوکس کامپایل خواهد شد.
کاربرد در Kubernetes
در کد منبع Kubernetes، از //go:build
بهطور گستردهای استفاده میشود، زیرا Kubernetes یک سیستم چندسکویی (cross-platform) است و این دستور برای کامپایل روی سیستمها و معماریهای مختلف ضروری است:
go:generate
دستور //go:generate
معمولاً برای تولید کد در مرحله ساخت (build) یا توسعه (development) استفاده میشود. این دستور بهصورت کامنت ویژهای در کد قرار میگیرد و برای اجرای ابزارها و دستورات خارجی جهت تولید فایلهای کد موردنیاز به کار میرود.
کاربردهای //go:generate
از این دستور معمولاً برای تولید انواع فایلهای کد مانند موارد زیر استفاده میشود:
-
فایلهای Mock برای تست
-
فایلهای Protobuf برای ارتباطات gRPC
-
متدهای Deep Copy برای کپی عمیق دادهها
//go:generate mockgen -source=service.go -destination=mock_service.go -package=mocks
این دستور، ابزار mockgen
را اجرا میکند تا فایلهای موک (mock) از service.go
ایجاد کند.
💡 نکته: دستورات
//go:generate
فقط در هنگام اجرای دستورgo generate
اجرا میشوند و در فرآیند معمول کامپایل تأثیری ندارند.
//go:generate mockgen -source=example.go -destination=mock_example.go -package=main
type Example interface {
DoSomething() error
}
// generated mock_example.go
// MockExample is a mock of Example interface.
type MockExample struct {
ctrl *gomock.Controller
recorder *MockExampleMockRecorder
}
// MockExampleMockRecorder is the mock recorder for MockExample.
type MockExampleMockRecorder struct {
mock *MockExample
}
// NewMockExample creates a new mock instance.
func NewMockExample(ctrl *gomock.Controller) *MockExample {
mock := &MockExample{ctrl: ctrl}
mock.recorder = &MockExampleMockRecorder{mock}
return mock
}
// ... more code skipped
go:nolint
دستور //go:nolint
برای غیرفعال کردن بررسیهای استاتیک کد توسط ابزارهایی مانند golangci-lint
استفاده میشود. این دستور باعث میشود که در بخشهای خاصی از کد یا حتی کل یک فایل، هشدارها و خطاهای تحلیل استاتیک گزارش نشوند.
نحوه استفاده از //go:nolint
بهصورت کلی، این دستور میتواند تمام بررسیها را غیرفعال کند یا مشخص کند که فقط بررسیهای خاصی غیرفعال شوند.
۱. غیرفعال کردن همه بررسیهای Lint
//go:nolint
func unusedFunction() {
// این تابع بدون هشدار از lint باقی میماند
}
۲. غیرفعال کردن Lint برای بررسیهای خاص
//go:nolint:unused,deadcode
func unusedFunction() {
// فقط خطاهای مربوط به unused و deadcode نادیده گرفته میشوند
}
موارد استفاده از //go:nolint
این دستور معمولاً در شرایطی به کار میرود که نیاز به بررسیهای کمتر و انعطافپذیری بیشتر داریم، مانند:
-
فایلهای Mock برای تست
-
تستهای خاصی که نیازی به بررسی ندارند
-
کدهایی که عمداً یک رفتار خاص دارند و lint نباید به آنها گیر بدهد
💡 نکته: استفادهی زیاد از
//go:nolint
توصیه نمیشود، زیرا ممکن است مشکلات واقعی در کد نادیده گرفته شوند.
دایرکتیو های دیگر
علاوه بر //go:build
، //go:generate
و //go:nolint
، تعدادی دستورالعمل دیگر در Go وجود دارند که کمتر استفاده میشوند اما همچنان میتوانند مفید باشند. در ادامه به این دستورالعملها و کاربردهایشان میپردازیم:
۱. //go:noescape
– بهینهسازی عملکرد (Performance Optimization)
این دستور از تحلیل فرار اشارهگرها (Pointer Escape Analysis) جلوگیری میکند، بنابراین Go از مقداردهی در Heap اجتناب کرده و عملکرد بهتری ارائه میدهد.
۲. //go:noinline
– غیرفعال کردن Inline برای دیباگ و تست عملکرد
در Go، توابع بهطور پیشفرض inline میشوند (برای افزایش سرعت اجرا). این دستور باعث میشود تابع inline نشود که در تست و دیباگ بسیار مفید است.
۳. //go:norace
– جلوگیری از تحلیل Race Condition
در Go، ابزار -race
برای شناسایی Race Condition در دستورات همزمان استفاده میشود. این دستور از تزریق کد بررسی Race Condition جلوگیری میکند.
۴. //go:nosplit
– جلوگیری از بررسی و تقسیم استک (Stack Splitting)
در Go، برای مدیریت بهینه حافظه، توابع بهطور خودکار Stack Splitting انجام میدهند. این دستور باعث میشود که کامپایلر بررسیهای مربوط به فضای استک را غیرفعال کند.
۵. //go:nocheckptr
– غیرفعال کردن بررسی اعتبار اشارهگرها
این دستور باعث میشود که Go بررسیهای مربوط به اعتبار اشارهگرها (Pointer Validity Check) را غیرفعال کند.
جمعبندی
✅ این دستورالعملهای خاص برای بهینهسازی، دیباگ و عملکرد استفاده میشوند، اما در شرایط عادی کمتر موردنیاز هستند.
🚨 برخی از آنها، مانند //go:norace
و //go:nocheckptr
، اگر بهدرستی استفاده نشوند، میتوانند منجر به رفتارهای ناامن شوند.
اولین نفر باش که نظر ثبت میکنی :) یعنی یه کامنت به ما نمیرسه 😁