অনুবাদ:
এটি একটি সাধারণ Go অ্যাপ্লিকেশন প্রজেক্টের লেআউট। মনে রাখবেন, এটি কন্টেন্টের দিক থেকে সাধারণ কারণ এটি শুধুমাত্র সাধারণ লেআউটের উপর গুরুত্ব দিচ্ছে, ভিতরের উপাদানগুলোর উপর নয়। এটি উচ্চস্তরের (high-level) একটি গাইড, যা প্রজেক্ট স্ট্রাকচার আরও গভীরভাবে কিভাবে সাজানো যায়, সে বিষয়ে বিস্তারিত আলোচনা করে না। উদাহরণস্বরূপ, এটি সুশৃঙ্খল নির্মাণ কৌশল (Clean Architecture) -এর মতো কাঠামোতে কিভাবে প্রজেক্ট সাজানো হয়, সেটি কাভার করে না।
এটি Go মূল ডেভেলপমেন্ট টিম কর্তৃক নির্ধারিত কোনো অফিসিয়াল স্ট্যান্ডার্ড নয়। বরং এটি Go ইকোসিস্টেমে ব্যবহৃত কিছু প্রচলিত এবং নতুনভাবে গড়ে ওঠা প্রজেক্ট লেআউট প্যাটার্নের একটি সংকলন। এর মধ্যে কিছু প্যাটার্ন অন্যগুলোর তুলনায় বেশি জনপ্রিয়।
এতে আরও কিছু ছোটখাটো উন্নয়ন (enhancement) এবং এমন কিছু সাপোর্টিং ডিরেক্টরিও রয়েছে, যেগুলো বাস্তব জীবনের বড় ধরনের অ্যাপ্লিকেশনে সাধারণত ব্যবহৃত হয়।
মনে রাখবেন, মূল Go টিম Go প্রজেক্ট স্ট্রাকচারের জন্য কিছু চমৎকার সাধারণ নির্দেশনা প্রদান করে যেমন, একটি প্রজেক্ট যখন অন্য কোথাও থেকে ইমপোর্ট বা ইনস্টল করা হয়, তখন সেটির অর্থ কী হয়।
এ বিষয়ে আরও বিস্তারিত জানতে অফিসিয়াল Go ডকুমেন্টেশনের Organizing a Go module পেজটি দেখুন।
এই নির্দেশনায় internal এবং cmd ডিরেক্টরির প্যাটার্ন (যা নিচে ব্যাখ্যা করা হয়েছে) সহ আরও গুরুত্বপূর্ণ তথ্য অন্তর্ভুক্ত রয়েছে।
যদি আপনি Go শিখছেন বা নিজের জন্য কোনো PoC (Proof of Concept) বা একটি সাধারণ প্রজেক্ট তৈরি করছেন, তাহলে এই প্রজেক্ট লেআউটটি আপনার জন্য খুব বেশি জটিল হবে। এর বদলে খুব সহজ কিছু দিয়ে শুরু করুন (একটা মাত্র main.go ফাইল এবং go.mod ফাইল যথেষ্ট)।কিন্তু আপনার প্রজেক্ট বড় হওয়া সাথে সাথে মনে রাখবেন, কোডটি সুশৃঙ্খলভাবে সাজানো থাকা খুব গুরুত্বপূর্ণ, না হলে কোডটা এলোমেলো হয়ে যাবে যেখানে অনেক লুকানো নির্ভরশীলতা (dependencies) এবং গ্লোবাল স্টেট থাকবে।
যখন আপনার প্রজেক্টে আরো মানুষ কাজ করবে, তখন আরও বেশি স্ট্রাকচার বা বিন্যাসের প্রয়োজন হবে।সেই সময়ই প্যাকেজ/লাইব্রেরি ব্যবস্থাপনার জন্য একটি সাধারণ পদ্ধতি নেয়া গুরুত্বপূর্ণ হয়ে ওঠে।যখন আপনার একটি ওপেন সোর্স প্রজেক্ট থাকে বা অন্য প্রজেক্টগুলো আপনার প্রজেক্টের কোড ইমপোর্ট করে, তখন প্রাইভেট (অর্থাৎ internal) প্যাকেজ এবং কোড থাকা খুব জরুরি হয়ে পড়ে।রিপোজিটরি ক্লোন করুন, যা প্রয়োজন তা রাখুন আর বাকিটা মুছে ফেলুন! শুধু সেটা সেখানে আছে বলে আপনাকে সবকিছু ব্যবহার করতেই হবে এমন নয়।এই প্যাটার্নগুলোর কোনোটা প্রতিটি প্রজেক্টে ব্যবহার হয় না। এমনকি vendor প্যাটার্নও সার্বজনীন নয়।
Go 1.14 এর সাথে Go Modules অবশেষে প্রোডাকশনের জন্য প্রস্তুত।
আপনার যদি Go Modules ব্যবহার না করার কোনো বিশেষ কারণ না থাকে, তাহলে অবশ্যই Go Modules ব্যবহার করুন।
এক্ষেত্রে আপনাকে $GOPATH বা আপনার প্রজেক্ট কোথায় রাখতে হবে তা নিয়ে চিন্তা করার দরকার নেই।
রিপোজিটরির বেসিক go.mod ফাইল ধরে নেয় যে আপনার প্রজেক্ট GitHub-এ হোস্ট করা আছে, কিন্তু এটি বাধ্যতামূলক নয়।
মডিউল পাথ যেকোনো হতে পারে, তবে প্রথম মডিউল পাথের অংশে একটি ডট (.) থাকা উচিত। (Go-এর বর্তমান ভার্সন এটা আর কঠোরভাবে প্রযোজ্য করে না, কিন্তু যদি আপনি কিছু পুরোনো ভার্সন ব্যবহার করেন তাহলে এটা না থাকলে বিল্ড ফেল হতে পারে।)
এ বিষয়ে আরো জানতে চাইলে Issues 37554 এবং 32819 দেখতে পারেন।
এই প্রজেক্ট লেআউটটি ইচ্ছাকৃতভাবে সাধারণ রাখা হয়েছে এবং এটি কোনো নির্দিষ্ট Go প্যাকেজ স্ট্রাকচার চাপিয়ে দেয় না।
এটি একটি কমিউনিটি উদ্যোগ।যদি আপনি কোনো নতুন প্যাটার্ন দেখতে পান বা মনে করেন বিদ্যমান প্যাটার্নগুলোর মধ্যে কোনোটা আপডেট হওয়া প্রয়োজন, তাহলে অনুগ্রহ করে একটি ইস্যু খুলুন।
নামকরণ (naming), ফরম্যাটিং এবং স্টাইল নিয়ে সাহায্যের প্রয়োজন হলে প্রথমে gofmt এবং staticcheck চালিয়ে শুরু করুন। পুরানো স্ট্যান্ডার্ড linter, golint এখন অব্যবহৃত (deprecated) এবং আর রক্ষণাবেক্ষণ করা হয় না; তাই staticcheck-এর মতো রক্ষণাবেক্ষিত লিন্টার ব্যবহার করার পরামর্শ দেওয়া হয়।সাথে সাথে নিচের Go কোড স্টাইল গাইডলাইন এবং সুপারিশগুলো পড়া নিশ্চিত করুন:
অতিরিক্ত তথ্যের জন্য Go Project Layout পৃষ্ঠা দেখুন।
নামকরণ এবং প্যাকেজ সংগঠনের বিষয়াদি এবং অন্যান্য কোড স্ট্রাকচার সুপারিশ সম্পর্কিত আরও তথ্য:
প্যাকেজ-ভিত্তিক ডিজাইন নির্দেশিকা এবং আর্কিটেকচার স্তর সম্পর্কে একটি চীনা পোস্ট
এই প্রজেক্টের জন্য মূল অ্যাপ্লিকেশনসমূহ।
প্রতিটি অ্যাপ্লিকেশনের জন্য ডিরেক্টরির নাম অবশ্যই সেই এক্সিকিউটেবলের(executable ) নামের সঙ্গে মিলতে হবে যা আপনি রাখতে চান (যেমন, /cmd/myapp)।
অ্যাপ্লিকেশন ডিরেক্টরিতে বেশি কোড রাখবেন না। যদি মনে করেন কোডটি অন্য প্রজেক্টে ইমপোর্ট করে ব্যবহার করা যেতে পারে, তাহলে কোডটি /pkg ডিরেক্টরিতে থাকা উচিত।
আর যদি কোডটি পুনঃব্যবহারযোগ্য না হয় অথবা আপনি চান না অন্যরা এটি ব্যবহার করুক, তাহলে কোডটি /internal ডিরেক্টরিতে রাখুন।অন্যরা কী করবে সেটা আপনি অবাক হয়ে দেখবেন, তাই আপনার ইচ্ছেটা স্পষ্ট করে রাখুন!
সাধারণত একটি ছোট main ফাংশন থাকে, যা /internal এবং /pkg ডিরেক্টরি থেকে কোড ইমপোর্ট করে চালায়, আর অন্য কিছু করে না।
উদাহরণ দেখতে /cmd ডিরেক্টরি দেখুন।
প্রাইভেট অ্যাপ্লিকেশন এবং লাইব্রেরি কোডের জন্য।এই কোডগুলো আপনি চান না অন্যরা তাদের অ্যাপ্লিকেশন বা লাইব্রেরিতে ইমপোর্ট করুক।
মনে রাখবেন, এই লেআউট প্যাটার্নটি Go কম্পাইলার নিজেই প্রয়োগ করে। বিস্তারিত জানতে Go 1.4 release notes দেখুন।আপনি শুধু টপ-লেভেল /internal ডিরেক্টরিতে সীমাবদ্ধ নন। আপনার প্রজেক্টের যেকোনো স্তরে একাধিক /internal ডিরেক্টরি থাকতে পারে।
ঐচ্ছিকভাবে, আপনি আপনার internal প্যাকেজগুলোতে আরও একটু স্ট্রাকচার যোগ করতে পারেন, যাতে শেয়ার করা এবং শেয়ার না করা কোড আলাদা করা যায়।ছোট প্রজেক্টগুলোর জন্য এটি বাধ্যতামূলক নয়, তবে কোড ব্যবহারের উদ্দেশ্য বোঝাতে ভিজ্যুয়াল clue হিসেবে ভালো।
আপনার প্রকৃত অ্যাপ্লিকেশন কোড /internal/app (যেমন, /internal/app/myapp) ডিরেক্টরিতে রাখতে পারেন, আর সেই অ্যাপগুলো দ্বারা শেয়ার করা কোড /internal/pkg (যেমন, /internal/pkg/myprivlib) এ রাখতে পারেন।
আপনি internal ডিরেক্টরি ব্যবহার করে প্যাকেজগুলো প্রাইভেট বানান।যদি কোনো প্যাকেজ internal ডিরেক্টরির মধ্যে থাকে, তবে অন্য প্যাকেজগুলো সেটি ইমপোর্ট করতে পারবে না যতক্ষণ না তারা একটি সাধারণ উপরের লেভেলের ডিরেক্টরির অধীনে থাকে।এছাড়া এটি একমাত্র ডিরেক্টরি যার নাম Go ডকুমেন্টেশনে উল্লেখ রয়েছে এবং যা কম্পাইলার দ্বারা বিশেষভাবে হ্যান্ডল করা হয়।
এখানে এমন লাইব্রেরি কোড রাখা হয় যেগুলো বাইরের অ্যাপ্লিকেশনগুলোর দ্বারা ব্যবহারযোগ্য (যেমন, /pkg/mypubliclib)।অন্য প্রজেক্টগুলো এই লাইব্রেরিগুলো ইমপোর্ট করবে এবং কাজ করবে বলে ধরে নেবে, তাই কিছু এখানে রাখার আগে দুইবার ভাবুন :)।মনে রাখবেন, internal ডিরেক্টরি ব্যবহার করাই সবচেয়ে ভালো উপায় কোনো প্যাকেজকে প্রাইভেট রাখতে, কারণ এটি Go কম্পাইলার দ্বারা জোরপূর্বক প্রয়োগ হয়।তবুও /pkg ডিরেক্টরি ব্যবহার করা ভালো একটি উপায় অন্যদেরকে স্পষ্টভাবে জানিয়ে দিতে যে, এখানকার কোড তারা নিরাপদে ব্যবহার করতে পারে।Travis Jeffery-এর I’ll take pkg over internal ব্লগ পোস্টে pkg এবং internal ডিরেক্টরি নিয়ে ভালো ব্যাখ্যা দেওয়া আছে — কবে কোনটি ব্যবহার করা উচিত তা নিয়ে।
এছাড়া এটি হলো Go কোডকে এক জায়গায় গুছিয়ে রাখার একটি উপায়, বিশেষ করে যখন আপনার রুট ডিরেক্টরিতে অনেক non-Go কম্পোনেন্ট বা ফোল্ডার থাকে। এতে বিভিন্ন Go টুল চালানো সহজ হয়। (এই বিষয়ে আরও আলোচনা হয়েছে: GopherCon EU 2018 Best Practices for Industrial Programming , GopherCon 2018:Kat Zien: How Do You Structure Your Go Apps এবং GoLab 2018 – Massimiliano Pippi: Project layout patterns in Go.
আপনি যদি দেখতে চান কোন কোন জনপ্রিয় Go রিপোজিটরি এই লেআউট প্যাটার্ন ব্যবহার করছে, তাহলে /pkg ডিরেক্টরিটি দেখুন।এই লেআউটটি অনেক সাধারণ, তবে সবার দ্বারা গৃহীত নয়, এবং Go কমিউনিটির কেউ কেউ এটি ব্যবহারের সুপারিশও করে না।
যদি আপনার অ্যাপ প্রজেক্টটি খুব ছোট হয় এবং অতিরিক্ত স্তর (nesting) বড় কোনো উপকার না করে, তাহলে এটি ব্যবহার না করলেও চলবে (অবশ্য আপনি চাইলে করতেই পারেন :-))।যখন আপনার প্রজেক্ট বড় হতে শুরু করবে এবং রুট ডিরেক্টরিটি বেশ ব্যস্ত হয়ে যাবে (বিশেষ করে অনেক non-Go উপাদান থাকলে), তখন এ নিয়ে ভাবা উচিত।
pkg ডিরেক্টরির উৎপত্তিঃপুরোনো Go সোর্স কোডে pkg ব্যবহার হতো প্যাকেজগুলোর জন্য। পরে কমিউনিটির বিভিন্ন Go প্রজেক্ট এটি অনুকরণ করতে শুরু করে।(বিস্তারিত জানতে Brad Fitzpatrick এর টুইটটি দেখুন)।
অ্যাপ্লিকেশনের ডিপেনডেন্সিগুলো (হাতে বা আপনার পছন্দের ডিপেনডেন্সি ম্যানেজমেন্ট টুল — যেমন Go-এর নতুন বিল্ট-ইন Go Modules ফিচার) দ্বারা ম্যানেজ করা হয়।go mod vendor কমান্ড চালালে এটি আপনার জন্য /vendor ডিরেক্টরি তৈরি করবে।মনে রাখবেন, যদি আপনি Go 1.14 ব্যবহার না করেন, তাহলে go build কমান্ডে -mod=vendor ফ্ল্যাগ যুক্ত করতে হতে পারে, কারণ Go 1.14-এ এটি ডিফল্টভাবে চালু থাকে।
আপনি যদি একটি লাইব্রেরি তৈরি করছেন, তাহলে আপনার অ্যাপ্লিকেশনের ডিপেনডেন্সিগুলো /vendor ডিরেক্টরিতে কমিট করবেন না।
আরও একটি বিষয় Go 1.13 থেকে Go module proxy ফিচার চালু করেছে, যেখানে ডিফল্টভাবে https://proxy.golang.org ব্যবহার করা হয় মডিউল প্রোক্সি সার্ভার হিসেবে।এটা আপনার সব চাহিদা ও সীমাবদ্ধতার সঙ্গে মানিয়ে যায় কিনা, তা জানতে এই লিংকে আরও পড়ুন।যদি মানিয়ে যায়, তাহলে /vendor ডিরেক্টরির আর প্রয়োজন হবে না।
/apiOOpenAPI/Swagger specs, JSON schema files, protocol definition files।
উদাহরণ দেখতে /api ডিরেক্টরি দেখুন।
/Webওয়েব অ্যাপ্লিকেশনের নির্দিষ্ট কম্পোনেন্ট যেমন: স্ট্যাটিক ওয়েব অ্যাসেটস, সার্ভার-সাইড টেমপ্লেট এবং SPA (Single Page Application) এখানে থাকে।
/configsকনফিগারেশন ফাইল টেমপ্লেট বা ডিফল্ট কনফিগ সংরক্ষণের জন্য।
confd বা consul-template এর টেমপ্লেট ফাইল এখানে রাখুন।
/initসিস্টেম init (systemd, upstart, sysv) এবং প্রসেস ম্যানেজার/সুপারভাইজার (runit, supervisord) এর কনফিগারেশন।
/scriptsবিভিন্ন build, install, analysis ইত্যাদি কাজের জন্য প্রয়োজনীয় স্ক্রিপ্ট। এই স্ক্রিপ্টগুলো রুট লেভেলের Makefile-কে ছোট ও সহজ রাখে। (উদাহরণ:https://github.com/hashicorp/terraform/blob/main/Makefile)
উদাহরণ দেখতে /scripts ডিরেক্টরি দেখুন।
/buildপ্যাকেজিং এবং Continuous Integration সংক্রান্ত ফাইল।
ক্লাউড (AMI), কনটেইনার (Docker), বা অপারেটিং সিস্টেম (deb, rpm, pkg) প্যাকেজের কনফিগারেশন ও স্ক্রিপ্টগুলো /build/package ডিরেক্টরিতে রাখুন।
CI টুলস(travis, circle, Drone) ইত্যাদির কনফিগারেশন ও স্ক্রিপ্টগুলো
/build/ci ডিরেক্টরিতে রাখুন।মনে রাখবেন, কিছু CI টুল (যেমন Travis CI) কনফিগারেশন ফাইলের অবস্থান নিয়ে খুব সংবেদনশীল।সম্ভব হলে /build/ci ডিরেক্টরিতে কনফিগ ফাইল রেখে সেগুলোকে সেই অবস্থানে লিংক করে দিন, যেখানে ওই টুলগুলো ফাইল খুঁজে পায়।
/deploymentsIaaS, PaaS, সিস্টেম ও কন্টেইনার অর্কেস্ট্রেশন ডিপ্লয়মেন্ট কনফিগারেশন ও টেমপ্লেট(যেমন: docker-compose, kubernetes/helm, terraform)।অনেক ক্ষেত্রে এই ডিরেক্টরির নাম /deploy হয়ে থাকে, বিশেষ করে Kubernetes ডিপ্লয়ড অ্যাপ্লিকেশনে।
/testঅতিরিক্ত এক্সটার্নাল টেস্ট অ্যাপ ও টেস্ট ডেটা।আপনি যেভাবে ইচ্ছা /test ডিরেক্টরি সাজাতে পারেন।বড় প্রজেক্টের ক্ষেত্রে একটি আলাদা data সাবডিরেক্টরি রাখা যুক্তিযুক্ত।
উদাহরণস্বরূপ, আপনি চাইলে /test/data বা /test/testdata ব্যবহার করতে পারেন — বিশেষ করে যদি আপনি চান Go সেই ডিরেক্টরির ভিতরের জিনিসগুলো উপেক্ষা (ignore) করুক।Go এছাড়াও এমন ডিরেক্টরি বা ফাইল উপেক্ষা করে যেগুলোর নাম . বা _ দিয়ে শুরু, তাই নামকরণের ক্ষেত্রে বেশ স্বাধীনতা আছে।
উদাহরণ দেখতে /test ডিরেক্টরি দেখুন।
/docsডিজাইন এবং ইউজার ডকুমেন্টেশন (godoc দিয়ে জেনারেট হওয়া ডকুমেন্টেশনের পাশাপাশি)।
উদাহরণ দেখতে /docs ডিরেক্টরি দেখুন।
/toolsপ্রজেক্টে ব্যবহৃত সহায়ক টুলস।এই টুলসগুলো /pkg এবং /internal ডিরেক্টরি থেকে কোড ইমপোর্ট করতে পারে।
উদাহরণ দেখতে /tools ডিরেক্টরি দেখুন।
/examplesআপনার অ্যাপ্লিকেশন বা পাবলিক লাইব্রেরির উদাহরণ কোড।
উদাহরণ দেখতে /examples ডিরেক্টরি দেখুন।
/third_partyবাইরের হেল্পার টুলস, ফর্ক করা কোড, এবং অন্যান্য 3rd-party ইউটিলিটি (যেমনঃ Swagger UI)।
/githooksGit হুকস ।
/assetsরিপোজিটরির সাথে সংযুক্ত অন্যান্য ফাইল (যেমন: ছবি, লোগো, মিডিয়া ফাইল ইত্যাদি)।
/websiteযদি আপনি GitHub Pages ব্যবহার না করেন, তাহলে আপনার প্রজেক্টের ওয়েবসাইট সংক্রান্ত ফাইল এখানে রাখা উচিত।
উদাহরণ দেখতে /website ডিরেক্টরি দেখুন।
/srcকিছু Go প্রজেক্টে /src ডিরেক্টরি দেখা যায়, তবে এটা সাধারণত তখন হয় যখন ডেভেলপাররা Java ব্যাকগ্রাউন্ড থেকে এসেছে, যেখানে এটি একটি প্রচলিত প্যাটার্ন।
Go-তে এটি ব্যবহার না করাই উত্তম। কারণ আপনি চাইবেন না যে আপনার Go কোড বা প্রজেক্ট দেখতে Java-এর মতো হোক। :)
আপনার প্রজেক্টে থাকা /src ডিরেক্টরিকে Go-এর ওয়ার্কস্পেসের /src ডিরেক্টরির সঙ্গে মিশিয়ে ফেলবেন না।এটা বোঝার জন্য Go-এর অফিসিয়াল গাইড How to Write Go Code দেখে নেওয়া উচিত।$GOPATH এনভায়রনমেন্ট ভ্যারিয়েবলটি আপনার (বর্তমান) Go ওয়ার্কস্পেস-কে নির্দেশ করে — ডিফল্টভাবে এটি নন-Windows সিস্টেমে $HOME/go ফোল্ডার।এই ওয়ার্কস্পেসে তিনটি শীর্ষ লেভেলের ডিরেক্টরি থাকে: /pkg,/bin,/src ।আপনার প্রকৃত প্রোজেক্টটি সাধারণত /src এর নিচে একটি সাব-ডিরেক্টরি হিসেবে থাকে,তাই, যদি আপনি নিজেই আপনার প্রোজেক্টে আরেকটি /src ডিরেক্টরি রাখেন, তাহলে আপনার কোডের পাথ দেখতে এমন হবে:
/some/path/to/workspace/src/your_project/src/your_code.go।যদিও Go 1.11 থেকে আপনার প্রোজেক্ট GOPATH-এর বাইরে রাখা সম্ভব হয়েছে,তবুও এই ধরণের লেআউট প্যাটার্ন (দ্বৈত /src) ব্যবহার করাটা ভালো আইডিয়া নয়।
Go Report Card - এটি gofmt, go vet, gocyclo, golint, ineffassign, license এবং misspell দিয়ে আপনার কোড বিশ্লেষণ করে। github.com/golang-standards/project-layout এর পরিবর্তে আপনার প্রজেক্টের ইউআরএল দিন।
GoDoc - এটি আপনার GoDoc ডকুমেন্টেশনের একটি অনলাইন সংস্করণ প্রদান করে। লিংকটি আপনার প্রজেক্ট অনুযায়ী পরিবর্তন করুন।
Pkg.go.dev - Go প্যাকেজের ডকুমেন্টেশন ও খোঁজার জন্য এটি একটি নতুন প্ল্যাটফর্ম। ব্যাজ জেনারেটর টুল ব্যবহার করে ব্যাজ তৈরি করুন।
রিলিজ (Release) - আপনার প্রজেক্টের সর্বশেষ রিলিজ ভার্সন দেখাবে। GitHub লিংকটি আপনার প্রজেক্ট অনুসারে পরিবর্তন করুন।
একটি আরও মতভেদপূর্ণ (opinionated) প্রজেক্ট টেমপ্লেট তৈরি করার কাজ চলছে, যেখানে নমুনা কনফিগারেশন, স্ক্রিপ্ট এবং কোড অন্তর্ভুক্ত থাকবে।