استاندارد کدنویسی Go
کد بکاند باید ساده، قابل مشاهده و مطابق Idiomهای Go باشد. خوانایی و Correctness بر اختصار، Abstraction زودهنگام یا استفاده نمایشی از Patternها اولویت دارد.
نسخه و Toolchain
go.modنسخه Major/Minor تصویبشده را مشخص میکند و CI با آخرین Patch همان خط اجرا میشود.- Image ساخت باید نسخه کامل Toolchain و Digest پایه را Pin کند.
- ارتقای Patch پس از CI خودکار است؛ ارتقای Major با ADR و بررسی Release Note انجام میشود.
go mod tidyنباید Diff غیرمنتظره باقی بگذارد وgo mod verifyدر CI اجرا میشود.- Dependency فقط برای نیاز واقعی اضافه میشود؛ کتابخانه کوچک بدون مزیت روشن با Standard Library جایگزین میشود.
- HTTP Server، Routing و قرارداد Middleware با
net/httpوhttp.ServeMuxپیادهسازی میشوند و Feature به Context اختصاصی Framework وابسته نمیشود.
قالب و نامگذاری
gofmtوgoimportsاجباریاند و CI هر Diff قالببندی را رد میکند.- نام Package کوتاه، lowercase، بدون underscore و بدون تکرار نام والد است.
- نام Exportشده باید Doc Comment معنادار داشته باشد؛ نام محلی کوتاه فقط وقتی دامنه آن کوتاه است مجاز است.
- Acronymها یکدست نوشته میشوند:
ID،URL،HTTPوOTP. - Boolean با مفهوم مثبت و قابل خواندن نامگذاری میشود؛ مانند
isActiveدر JSON وactiveدر Go در صورت نبود ابهام. - Magic Number، Status و Permission به Constant دامنهای تبدیل میشوند.
تابع و Interface
- تابع باید یک مسئولیت داشته و مسیر اصلی آن کمتورفتگی باشد؛ Guard Clause ترجیح دارد.
- ورودیهای مرتبط با رفتار در یک Command یا Value Object جمع میشوند، نه در فهرست بلند پارامترها.
- Interface کوچک و در سمت Consumer تعریف میشود. بازگرداندن Struct و پذیرفتن Interface اصل پیشفرض است.
- Interface خالی یا
anyدر Domain و Application فقط در مرز Serialization یا Telemetry و با دلیل روشن مجاز است. - Global Mutable State ممنوع است. Dependencyها در Composition Root تزریق میشوند.
- تکرار منطق یا Policy ممنوع است؛ کد مشترک فقط وقتی Extract میشود که رفتار یکسان، نام روشن، مالک مشخص و Test مستقل داشته باشد.
Context و Timeout
context.Contextنخستین پارامتر عملیات I/O یا عملیات قابل لغو است و در Struct ذخیره نمیشود.- Context ورودی از HTTP تا Database و Provider عبور میکند و با
context.Background()قطع نمیشود. - هر I/O باید Deadline داشته باشد؛ Timeout Provider از بودجه کلی درخواست کمتر است.
- Cancellation خطا نیست که پنهان شود؛
context.Canceledوcontext.DeadlineExceededبه پاسخ و Metric مناسب نگاشت میشوند. - Valueهای Context فقط برای metadata درخواست مانند Trace ID استفاده میشوند، نه Dependency یا داده کسبوکار.
مدیریت خطا
- خطا دقیقا یکبار و در مرز دارای Context ثبت میشود؛ لایههای پایین همان خطا را چندبار Log نمیکنند.
- خطا با
%wWrap میشود و تشخیص باerrors.Isیاerrors.Asانجام میشود، نه مقایسه متن. - Domain Error پایدار و قابل نگاشت به HTTP تعریف میشود؛ جزئیات Driver، SQL، Stack یا Provider به Client نشت نمیکند.
- Panic برای خطای برنامهنویسی است، نه ورودی کاربر یا خطای قابل انتظار. Middleware در مرز Process آن را Recover، ثبت و به خطای عمومی تبدیل میکند.
- نتیجه مالی یا Permission بر اساس Fail-open اجرا نمیشود؛ خطای Dependency به رد امن عملیات منجر میشود.
همزمانی
- هر Goroutine باید مالک Lifecycle، مسیر Cancellation و روش Wait مشخص داشته باشد.
- Goroutine بدون Bound، Channel بدون مالک و
time.Tickبدون Stop ممنوع است. - برای Fan-out از Limit همزمانی و
errgroupبا Context استفاده میشود. - Map مشترک باید Synchronization صریح داشته باشد؛ استفاده از
sync.Mapفقط پس از اندازهگیری و تناسب الگو مجاز است. go test -race ./...برای Pull Requestهای عادی اجرا میشود؛ آزمونهای بسیار سنگین میتوانند در Workflow زمانبندیشده جدا باشند.
Config و Secret
- Config در Startup از Environment یا Secret File خوانده، Validate و به Struct immutable تبدیل میشود.
- نبود Config الزامی باعث Fail-fast پیش از Listen شدن Server میشود.
- Secret، Token، OTP، DSN کامل و Credential هرگز در Repository، Error، Metric یا Log قرار نمیگیرد.
.envفقط برای Development محلی و خارج از Git است؛.env.exampleفقط Placeholder غیرواقعی دارد.- Rotation Keyها باید بدون Downtime ممکن باشد؛ Verifier حداقل Key فعال و Key قبلی را در بازه مهاجرت میشناسد.
Log و Audit
- Log عملیاتی با
log/slogبهصورت JSON و با فیلدهای ثابت مانندservice،version،environment،request_idوtrace_idتولید میشود. - متن آزاد جای فیلد ساختیافته را نمیگیرد و داده با Cardinality بالا وارد Label متریک نمیشود.
- شماره موبایل، نام، متن Ticket، محتوای فایل و داده مالی در Log Redact یا Tokenize میشوند.
- Audit Log دامنهای با Log عملیاتی یکی نیست؛ Audit تغییرناپذیر، Actor، Tenant، Action، Target، نتیجه، زمان و Correlation ID را ثبت میکند.
Definition of Done کد
- کد
gofmt،go vet، Lint، Test، Race Test وgovulncheckرا پاس میکند. - تغییر قرارداد با OpenAPI، Migration و مستند مرتبط همراه است.
- مسیر خطا، Authorization، Tenant Isolation و Idempotency آزمون دارد.
- Log یا Fixture شامل Secret و PII واقعی نیست.
- TODO بدون Issue، مالک و دلیل قابل پیگیری باقی نمانده است.