KoderKoder.ai
প্রাইসিংএন্টারপ্রাইজএডুকেশনবিনিয়োগকারীদের জন্য
লগ ইনশুরু করুন

প্রোডাক্ট

প্রাইসিংএন্টারপ্রাইজবিনিয়োগকারীদের জন্য

রিসোর্স

আমাদের সাথে যোগাযোগ করুনসহায়তাএডুকেশনব্লগ

লিগ্যাল

প্রাইভেসি পলিসিটার্মস অফ ইউজসিকিউরিটিঅ্যাকসেপ্টেবল ইউজ পলিসিঅ্যাবিউজ রিপোর্ট করুন

সোশ্যাল

LinkedInTwitter
Koder.ai
ভাষা

© 2026 Koder.ai. সর্বস্বত্ব সংরক্ষিত।

হোম›ব্লগ›Claude Code দিয়ে Go API স্ক্যাফোল্ডিং: ধারাবাহিক হ্যান্ডলার ও সার্ভিস
০১ জানু, ২০২৬·6 মিনিট

Claude Code দিয়ে Go API স্ক্যাফোল্ডিং: ধারাবাহিক হ্যান্ডলার ও সার্ভিস

Claude Code দিয়ে Go API স্ক্যাফোল্ডিং: এক পরিষ্কার handler-service-error প্যাটার্ন নির্ধারণ করুন, তারপর নতুন এন্ডপয়েন্ট জেনারেট করুন যা আপনার Go API জুড়ে ধারাবাহিক থাকে।

Claude Code দিয়ে Go API স্ক্যাফোল্ডিং: ধারাবাহিক হ্যান্ডলার ও সার্ভিস

কেন Go API বিশৃঙ্খল হয় যখন প্যাটার্নগুলো আগে স্থির করা না থাকে

Go API সাধারণত শুরুতে পরিষ্কার থাকে: কয়েকটি এন্ডপয়েন্ট, এক বা দুইজন ডেভেলপার, এবং সবকিছু প্রত্যেকের মনে থাকে। তারপর API বাড়ে, ফিচার চাপের মধ্যে শিপ হয়, এবং ছোট ছোট পার্থক্য এসে পড়ে। প্রতিটা পার্থক্য নির্দিষ্টভাবে ক্ষতিকর মনে না হলেও, একসঙ্গে এগুলো ভবিষ্যত সকল পরিবর্তন ধীর করে দেয়।

একটি সাধারণ উদাহরণ: এক হ্যান্ডলার JSON ডিকোড করে একটি স্ট্রাক্টে এবং 400 রিটার্ন করে সহায়ক একটি বার্তা, আরেকটি 422 রিটার্ন করে ভিন্ন আকারে, এবং তৃতীয়টি ত্রুটিগুলো ভিন্ন ফরম্যাটে লগ করে। এগুলো কম্পাইলেশনে ব্যর্থ করে না। এটি শুধু প্রতিটি নতুন কাজ করার সময় ধারাবাহিক সিদ্ধান্ত-গ্রহণ এবং ক্ষুদ্র রিরাইট তৈরি করে।

আপনি এই বিশৃঙ্খলা অনুভব করবেন এমন জায়গাগুলোতে যেমন:

  • এন্ডপয়েন্টভিত্তিক ভিন্ন ত্রুটি বডি, ফলে ক্লায়েন্টদের বিশেষ কেস রাখতে হয়।
  • সার্ভিস কখনো কাঁচা ডাটাবেস এরর রিটার্ন করে, কখনো “ফ্রেন্ডলি” এক্সপেরিয়েন্স দেয়।
  • নামকরণ কুড়েঘর (CreateUser, AddUser, RegisterUser) খোঁজাখুঁজি কঠিন করে তোলে।
  • ভ্যালিডেশন ঘোরে-ফিরে থাকে, ফলে একই বাগ বারবার ফিরে আসে।

এখানে "Scaffolding" মানে নতুন কাজের জন্য একটি পুনরাবৃত্তি যোগ্য টেমপ্লেট: কোড কোথায় যাবে, প্রতিটি লেয়ার কি করবে, এবং প্রতিক্রিয়াগুলো কেমন হবে। এটা অনেকটাই কোড উৎপন্ন করার চেয়ে একটি স্থির আকার লক করার ব্যাপার।

Claude-এর মতো টুল নতুন এন্ডপয়েন্ট দ্রুত scaffold করতে সাহায্য করতে পারে, কিন্তু এগুলো তখনই কার্যকর থাকে যখন আপনি প্যাটার্নকে একটি নিয়ম হিসেবে বিবেচনা করেন। আপনি নিয়ম নির্ধারণ করবেন, প্রতিটি ডিফ রিভিউ করবেন, এবং টেস্ট চালাবেন। মডেল স্ট্যান্ডার্ড অংশগুলো পূরণ করে; এটি আপনার আর্কিটেকচার পুনরায় নির্ধারণ করার অধিকার পায় না।

এক লেয়ার বিভাজন বাছাই করুন: handler, service, এবং data access

Go API তখনই সহজে বড় হয় যখন প্রতিটি অনুরোধ একই পথে চলে। নতুন এন্ডপয়েন্ট জেনারেট করার আগে এক লেয়ার বিভাজন বাছাই করুন এবং সেটির সাথে অনড় থাকুন।

দায়িত্বসমূহ, সহজভাবে রাখা

হ্যান্ডলারের কাজ কেবল HTTP: অনুরোধ পড়া, সার্ভিস কল করা, এবং রেসপন্স লেখা। এতে ব্যবসায়িক নিয়ম, SQL, বা "এই একটাই বিশেষ কেস" লজিক থাকা উচিত নয়।

সার্ভিস ইউজকেসের মালিক: ব্যবসায়িক নিয়ম, সিদ্ধান্ত, এবং রেপোজিটরি বা এক্সটার্নাল কলের মধ্যে অর্কেস্ট্রেশন। এটিতে HTTP সংক্রান্ত বিষয় (স্ট্যাটাস কোড, হেডার, অথবা কীভাবে ত্রুটি রেন্ডার করা হবে) থাকা উচিত নয়।

ডাটা অ্যাক্সেস (রিপো/স্টোর) পার্সিস্টেন্সের বিবরণ নিয়ন্ত্রণ করে। এটি সার্ভিসের উদ্দেশ্যকে SQL/কোয়েরি/ট্রানজেকশনে অনুবাদ করে। এখানে ব্যবসায়িক নিয়ম চেপে ধরা উচিত নয়, শুধুমাত্র মৌলিক ডাটা ইন্টেগ্রিটি সীমাবদ্ধতা থাকে।

একটি প্রায়োগিক আলাদা রাখার চেকলিস্ট:

  • Handler: ইনপুট পার্স করা, সার্ভিস কল করা, ত্রুটিকে HTTP-এ ম্যাপ করা, JSON লেখা
  • Service: ব্যবসায়িক নিয়ম প্রয়োগ করা, রিপোজ কল করা, ডোমেন রেজাল্ট বা টাইপেড এরর রিটার্ন করা
  • Data access: কুয়েরি চালানো, রো-গুলো স্ট্রাক্টে ম্যাপ করা, স্টোরেজ এরর রিটার্ন করা
  • Shared: সাধারণ এরর টাইপ এবং রেসপন্স হেল্পার
  • কোনো লেয়ার আরেকটিকে স্কিপ করবে না (হ্যান্ডলার কখনও সরাসরি রিপো কল করবে না)

ভ্যালিডেশনের জন্য এক নিয়ম

এক নিয়ম বেছে নিন এবং তা দিয়ে আপোষ করবেন না।

একটি সহজ পদ্ধতি:

  • হ্যান্ডলারগুলো "shape validation" করে (প্রয়োজনীয় ফিল্ড, মৌলিক ফরম্যাট)।
  • সার্ভিসগুলো "meaning validation" করে (পারমিশন, ইনভারিয়েন্ট, স্টেট)।

উদাহরণ: হ্যান্ডলার চেক করে email আছে কি না এবং ই-মেইল মতো দেখাচ্ছে কি। সার্ভিস চেক করে ওই ই-মেইল অনুমোদিত কি না এবং ইতিমধ্যেই ব্যবহার হচ্ছে কি না।

লেয়ারগুলোর মধ্যে কি যায়

শুরুতেই সিদ্ধান্ত নিন সার্ভিসগুলো ডোমেন টাইপ রিটার্ন করবে নাকি DTO।

একটি পরিষ্কার ডিফল্ট: হ্যান্ডলাররা request/response DTO ব্যবহার করে, সার্ভিস ডোমেন টাইপ ব্যবহার করে, এবং হ্যান্ডলার ডোমেনকে রেসপন্সে ম্যাপ করে। এতে সার্ভিস স্থির থাকে যদিও HTTP কন্ট্রাক্ট পরিবর্তিত হয়।

যদি ম্যাপিং ভারী মনে হয়, তখনও ধারাবাহিকতা রাখুন: সার্ভিস একটি ডোমেন টাইপ এবং একটি টাইপেড এরর রিটার্ন করুক, এবং JSON শেইপিং হ্যান্ডলারে রাখুন।

একটি স্ট্যান্ডার্ড ত্রুটি রেসপন্স এবং স্ট্যাটাস কোড ম্যাপ নির্ধারণ করুন

যদি আপনি চান যে জেনারেট হওয়া এন্ডপয়েন্টগুলো একই ব্যক্তির লেখা মনে হোক, তাহলে ত্রুটি রেসপন্স আগে থেকেই লক করে রাখুন। জেনারেশন তখনই ভালো ফল দেয় যখন আউটপুট ফরম্যাট অ-আলোচ্য: একটি JSON শেইপ, একটি স্ট্যাটাস-কোড ম্যাপ, এবং কি প্রকাশ করা হবে তার এক নিয়ম।

প্রথমে একটি একক ত্রুটি এনভেলপ শুরু করুন যা প্রতিটি এন্ডপয়েন্ট ফেলিওরের সময় রিটার্ন করে। এটিকে ছোট এবং পূর্বানুমেয় রাখুন:

{
  "code": "validation_failed",
  "message": "One or more fields are invalid.",
  "details": {
    "fields": {
      "email": "must be a valid email address",
      "age": "must be greater than 0"
    }
  },
  "request_id": "req_01HR..."
}

code মেশিনের জন্য (স্থিতিশীল ও পূর্বানুমেয়) এবং message মানুষের জন্য (ছোট ও নিরাপদ)। ঐচ্ছিক স্ট্রাকচার্ড ডেটা details-এ রাখুন। ভ্যালিডেশনের জন্য details.fields ম্যাপ সহজে জেনারেটযোগ্য এবং ক্লায়েন্টগুলোর কাছে ইনপুটের পাশে দেখানো সুবিধাজনক।

পরবর্তী ধাপে একটি স্ট্যাটাস কোড ম্যাপ লিখে সেটি মেনে চলুন। প্রতিটি এন্ডপয়েন্টে বিতর্ক যত কম, তত ভালো। যদি আপনি 400 এবং 422 দুটিই চান, বিভাজন স্পষ্টভাবে করে রাখুন:

  • bad_json -> 400 Bad Request (বিকৃত JSON)
  • validation_failed -> 422 Unprocessable Content (ভাল-ফর্ম্যাট করা JSON, অবৈধ ফিল্ড)
  • not_found -> 404 Not Found
  • conflict -> 409 Conflict (ডুপ্লিকেট কী, ভার্সন মিল না করা)
  • unauthorized -> 401 Unauthorized
  • forbidden -> 403 Forbidden
  • internal -> 500 Internal Server Error

আপনি কী লগ করবেন বনাম কী রিটার্ন করবেন তা নির্ধারণ করুন। একটি ভাল নিয়ম: ক্লায়েন্টকে একটি নিরাপদ মেসেজ এবং একটি request ID দিন; লগে পুরো এ্যারর এবং অভ্যন্তরীণ কনটেক্সট (SQL, আপস্ট্রীম পে-লোড, ইউজার আইডি) রাখুন যা কখনো লিক করা উচিত নয়।

শেষে, request_id স্ট্যান্ডার্ড করুন। ইনকামিং ID হেডার গ্রহণ করুন যদি থাকে (API গেটওয়ে থেকে), নচেৎ এজ-এ (মিডলওয়্যারে) একটি জেনারেট করুন। এটিকে কনটেক্সটে লাগান, লগে অন্তর্ভুক্ত করুন, এবং প্রতিটি ত্রুটি রেসপন্সে রিটার্ন করুন।

ফোল্ডার লেআউট ও নামকরণ যা জেনারেশনকে পূর্বানুমেয় করে

যদি আপনি চান স্ক্যাফোল্ডিং ধারাবাহিক থাকে, আপনার ফোল্ডার লেআউট সাধারণ এবং পুনরাবৃত্তিশীল হতে হবে। জেনারেটররা ধাঁচ অনুসরণ করে, কিন্তু যখন ফাইল ছড়িয়ে থাকে বা নাম প্রতিটি ফিচারে ভিন্ন হয় তখন তারা বিচলিত হয়ে পড়ে।

একটি নামকরণ কনভেনশন বেছে নিন এবং সেটার সঙ্গে আপোষ করবেন না। প্রতিটি জিনিসের জন্য একটি শব্দ নির্বাচন করুন এবং বজায় রাখুন: handler, service, repo, request, response। যদি রুট হয় POST /users, ফাইল ও টাইপের নাম users এবং create চারপাশে রাখুন (কখনো register বা addUser ব্যবহার করবেন না)।

একটি সাধারণ লেআউট যা সাধারণ লেয়ারগুলোর সাথে মেলে:

internal/
  httpapi/
    handlers/
    users_handler.go
  services/
    users_service.go
  data/
    users_repo.go
  apitypes/
    users_types.go

শেয়ারড টাইপগুলি কোথায় থাকবে তা সিদ্ধান্ত নিন, কারণ প্রকল্পগুলো প্রায়ই এখানেই বিশৃঙ্খল হয়ে পড়ে। একটি ব্যবহারযোগ্য নিয়ম:

  • API request/response টাইপ internal/apitypes-এ থাকবে (JSON এবং ভ্যালিডেশন প্রয়োজন অনুযায়ী)।
  • ডোমেন টাইপ সার্ভিস লেয়ারের কাছাকাছি থাকবে (ব্যবসায়িক নিয়ম অনুযায়ী)।

যদি কোনো টাইপে JSON ট্যাগ থাকে এবং ক্লায়েন্টের জন্য ডিজাইন করা হয়, তাহলে সেটাকে API টাইপ হিসেবে বিবেচনা করুন।

হ্যান্ডলারের ডিপেনডেন্সি ন্যূনতম রাখুন এবং সেই নিয়মটি স্পষ্টভাবে নির্ধারণ করুন:

  • Handlers শুধুমাত্র ইম্পোর্ট করবে: routing/http, context, apitypes, এবং services
  • Services ইম্পোর্ট করবে: domain types এবং data access
  • Data access ইম্পোর্ট করবে: ডাটাবেস ড্রাইভার এবং কুয়েরি হেল্পার
  • কোনো হ্যান্ডলার সরাসরি ডাটাবেস প্যাকেজ ইম্পোর্ট করবে না

রেপোর মধ্যে ছোট একটি প্যাটার্ন ডক রিপো রুটে লিখে রাখুন (প্লেইন Markdown ঠিক আছে)। ফোল্ডার ট্রি, নামকরণ নিয়ম, এবং একটি ছোট উদাহরণ ফ্লো (handler -> service -> repo, এবং প্রতিটি অংশ কোন ফাইলে থাকা উচিত) অন্তর্ভুক্ত করুন। এটি ঠিক সেই রেফারেন্স যা আপনি আপনার জেনারেটরে পেস্ট করবেন যাতে প্রতিবার নতুন এন্ডপয়েন্ট একই স্ট্রাকচারে মেলে।

একটি রেফারেন্স এন্ডপয়েন্ট তৈরি করুন যা প্যাটার্ন নির্ধারণ করে

Ship and test faster
Host your API after scaffolding so you can test real client behavior early.
Deploy App

দশটি এন্ডপয়েন্ট জেনারেট করার আগে একটি এন্ডপয়েন্ট তৈরি করুন যেটিতে আপনি আস্থাশীল। এটি গোল্ড স্ট্যান্ডার্ড: সেই ফাইলটি যা আপনি দেখিয়ে বলতে পারবেন, "নতুন কোডকে এভাবেই দেখাতে হবে।" আপনি এটি স্ক্র্যাচ থেকে লিখতে পারেন বা একটি বিদ্যমানকে রিফ্যাক্টর করতে পারেন যতক্ষণ না তা ম্যাচ করে।

হ্যান্ডলার পাতলা রাখুন। একটি চলা টিপ: হ্যান্ডলার ও সার্ভিসের মধ্যে একটি ইন্টারফেস রাখুন যাতে হ্যান্ডলার কনট্রাক্টের ওপর নির্ভর করে, কনক্রিট স্ট্রাকটির ওপর নয়।

রেফারেন্স এন্ডপয়েন্টে ভবিষ্যতে জেনারেটেড কোড কোথায় আটকে থাকতে পারে সেগুলোতে ছোট মন্তব্য রাখুন। সিদ্ধান্তগুলো ব্যাখ্যা করুন (কেন 400 বনাম 422, কেন create 201 রিটার্ন করে, কেন আপনি অভ্যন্তরীণ ত্রুটিগুলো সাধারণ বার্তার আড়াল করেন)। এমন মন্তব্য এড়িয়ে চলুন যা কেবল কোডকে পুনরাবৃত্তি করে।

রেফারেন্স এন্ডপয়েন্ট কাজ করলে হেল্পারগুলো জমা করুন যাতে প্রতিটি নতুন এন্ডপয়েন্টে ড্রিফটের সম্ভাবনা কমে। সবচেয়ে পুনঃব্যবহারযোগ্য হেল্পারগুলো সাধারণত:

  • JSON বাইন্ড করা এবং বিকৃত বডি হ্যান্ডেল করা
  • ইনপুট ভ্যালিডেট করা এবং ফিল্ড লেভেল এরর রিটার্ন করা
  • ধারাবাহিকভাবে JSON রাইট করা
  • ডোমেন এররকে HTTP স্ট্যাটাস কোডে ম্যাপ করা

নিচে "পাতলা হ্যান্ডলার + ইন্টারফেস" বাস্তবে কেমন দেখাতে পারে:

type UserService interface {
	CreateUser(ctx context.Context, in CreateUserInput) (User, error)
}

func (h *Handler) CreateUser(w http.ResponseWriter, r *http.Request) {
	var in CreateUserRequest
	if err := BindJSON(r, &in); err != nil {
		WriteError(w, ErrBadJSON) // 400: malformed JSON
		return
	}
	if err := Validate(in); err != nil {
		WriteError(w, err) // 422: validation details
		return
	}
	user, err := h.svc.CreateUser(r.Context(), in.ToInput())
	if err != nil {
		WriteError(w, err)
		return
	}
	WriteJSON(w, http.StatusCreated, user)
}

কয়েকটি টেস্ট দিয়ে এটিকে লক করুন (এমনকি একটি ছোট টেবিল টেস্টও ঠিক আছে এরর ম্যাপিংয়ের জন্য)। জেনারেশন তখনই ভালো কাজ করে যখন সেটির একটি পরিষ্কার লক্ষ্য থাকে যা অনুকরণ করা যায়।

ধাপে ধাপে: Claude কে একটি নতুন এন্ডপয়েন্ট তৈরি করতে বলুন যাতে তা ম্যাচ করে

সামঞ্জস্য শুরু হয় আপনি যা পেস্ট করেন এবং আপনি কী নিষিদ্ধ করেন তার উপর। একটি নতুন এন্ডপয়েন্টের জন্য দুইটি জিনিস দিন:

  1. আপনার রেফারেন্স এন্ডপয়েন্ট ("পারফেক্ট" উদাহরণ)
  2. একটি ছোট প্যাটার্ন নোট যা প্যাকেজ, ফাংশন এবং হেল্পারগুলোর নাম নির্দেশ করে যা এটি ব্যবহার করবে

1) প্রাসঙ্গিকতা প্রথম দিন (রেফারেন্স + নিয়ম)

হ্যান্ডলার, সার্ভিস মেথড, রিকোয়েস্ট/রেসপন্স টাইপ, এবং যেকোন শেয়ারড হেল্পার যা এন্ডপয়েন্টটি ব্যবহার করে তা অন্তর্ভুক্ত করুন। তারপর কনট্রাক্ট স্পষ্টভাবে বলুন:

  • রুট + মেথড (উদাহরণ: POST /v1/widgets)
  • রিকোয়েস্ট JSON ফিল্ড (required বনাম optional)
  • রেসপন্স JSON আকার
  • এরর কেস এবং স্ট্যাটাস কোড
  • আপনি কোন ফাইলগুলোর প্রত্যাশা করেন (এবং শুধুমাত্র ঐ ফাইলগুলো)

নামকরণ, প্যাকেজ পাথ এবং হেল্পার ফাংশন (WriteJSON, BindJSON, WriteError, আপনার ভ্যালিডেটর) ঠিক মিলাতে হবে বলে স্পষ্টভাবে বলুন।

2) আউটপুট ঠিক আপনার চাওয়াই ভাবে চান

একটি টাইট প্রম্পট "সহায়ক" রিফ্যাক্টরিংকে বন্ধ করে দেয়। উদাহরণ:

Using the reference endpoint below and the pattern notes, generate a new endpoint.
Contract:
- Route: POST /v1/widgets
- Request: {"name": string, "color": string}
- Response: {"id": string, "name": string, "color": string, "createdAt": string}
- Errors: invalid JSON -> 400; validation -> 422; duplicate name -> 409; unexpected -> 500
Output ONLY these files:
1) internal/http/handlers/widgets_create.go
2) internal/service/widgets.go (add method only)
3) internal/types/widgets.go (add types only)
Do not change: router setup, existing error format, existing helpers, or unrelated files.
Must use: package paths and helper functions exactly as in the reference.

আপনি যদি টেস্ট চান, সেগুলো স্পষ্টভাবে অনুরোধ করুন (এবং টেস্ট ফাইলের নাম দিন)। অন্যথায় মডেল সেগুলো স্কিপ করতে পারে বা নতুন টেস্ট সেটআপ উদ্ভাবন করতে পারে।

জেনারেশনের পরে দ্রুত একটি ডিফ চেক করুন। যদি এটি শেয়ারড হেল্পার, রাউটার রেজিস্ট্রেশন, বা আপনার স্ট্যান্ডার্ড এরর রেসপন্স পরিবর্তন করে, আউটপুট প্রত্যাখ্যান করুন এবং "do not change" নিয়মগুলো আরও কড়া করে পুনরায় বলুন।

একটি পুনরায় ব্যবহারযোগ্য প্রম্পট টেমপলেট অনুগত এন্ডপয়েন্ট স্ক্যাফোল্ডিংয়ের জন্য

আউটপুট ঠিকই থাকবে যতটা ইনপুট ধারাবাহিক। প্রতিবার একটি প্রম্পট টেমপলেট পুনরায় ব্যবহার করা এবং আপনার রেপোর একটি ছোট কনটেক্সট স্ন্যাপশট পেস্ট করা দ্রুততর উপায়।

প্রম্পট টেমপলেট

কপি করুন, পেস্ট করুন, এবং প্লেসহোল্ডারগুলো পূরণ করুন:

You are editing an existing Go HTTP API.

CONTEXT
- Folder tree (only the relevant parts):
  <paste a small tree: internal/http, internal/service, internal/repo, etc>
- Key types and patterns:
  - Handler signature style: <example>
  - Service interface style: <example>
  - Request/response DTOs live in: <package>
- Standard error response JSON:
  {
    "error": {
      "code": "invalid_argument",
      "message": "...",
      "details": {"field": "reason"}
    }
  }
- Status code map:
  invalid_json -> 400
  invalid_argument -> 422
  not_found -> 404
  conflict -> 409
  internal -> 500

TASK
Add a new endpoint: <METHOD> <PATH>
- Handler name: <Name>
- Service method: <Name>
- Request JSON example:
  {"name":"Acme"}
- Success response JSON example:
  {"id":"123","name":"Acme"}

CONSTRAINTS
- No new dependencies.
- Keep functions small and single-purpose.
- Match existing naming, folder layout, and error style exactly.
- Do not refactor unrelated files.

ACCEPTANCE CHECKS
- Code builds.
- Existing tests pass (add tests only if the repo already uses them for handlers/services).
- Run gofmt on changed files.

FINAL INSTRUCTION
Before writing code, list any assumptions you must make. If an assumption is risky, ask a short question instead.

এটি কাজ করে কারণ এটি তিনটি জিনিস জোর করে: একটি কনটেক্সট ব্লক (কী আছে), একটি কনস্ট্রেইন্ট ব্লক (কী করা যাবেনা), এবং স্পষ্ট JSON উদাহরণ (তাই শেইপগুলো ভ্রমণ করে না)। ফাইন্যাল ইনস্ট্রাকশন একটি সেফটি ক্যাচ: যদি মডেল অনিশ্চিত হয়, সেটা কোড লেখার আগে আপনাকে জানান।

বাস্তবসম্মত উদাহরণ: স্টাইল ভাঙা ছাড়াই একটি Create এন্ডপয়েন্ট যোগ করা

Reduce review back-and-forth
Iterate on naming, files, and error mapping with quick diffs in a chat workflow.
Build with Chat

ধরা যাক আপনি একটি "Create project" এন্ডপয়েন্ট যোগ করতে চান। লক্ষ্য সহজ: একটি নাম গ্রহণ করা, কয়েকটি নিয়ম চালু করা, সেটি স্টোর করা, এবং একটি নতুন আইডি রিটার্ন করা। জটিলতা হল একই handler-service-repo বিভাজন এবং একই ত্রুটি JSON রাখা।

একটি ধারাবাহিক ফ্লো দেখতে এমন:

  • Handler: JSON বাইন্ড, মৌলিক ফিল্ড ভ্যালিডেশন, সার্ভিস কল
  • Service: ব্যবসায়িক নিয়ম (যেমন ইউনিকনেস), রিপো কল, ডোমেন রেজাল্ট রিটার্ন
  • Repo: Postgres-এ লিখে জেনারেট করা ID রিটার্ন

হ্যান্ডলার যে অনুরোধ গ্রহণ করে তা এইরকম:

{ "name": "Roadmap", "owner_id": "u_123" }

সাফল্যে 201 Created রিটার্ন করুন। ID প্রতি বার এক স্থান থেকে আসা উচিত। উদাহরণস্বরূপ, Postgres সেটি জেনারেট করুক এবং রিপো তা রিটার্ন করুক:

{ "id": "p_456", "name": "Roadmap", "owner_id": "u_123", "created_at": "2026-01-09T12:34:56Z" }

দুটি বাস্তবসম্মত ব্যর্থতার পথ:

যদি ভ্যালিডেশন ব্যর্থ হয় (নাম অনুপস্থিত বা খুব ছোট), আপনার স্ট্যান্ডার্ড শেইপ ব্যবহার করে ফিল্ড-লেভেল এরর রিটার্ন করুন এবং আপনার নির্বাচিত স্ট্যাটাস কোড অনুসরণ করুন:

{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid request", "details": { "name": "must be at least 3 characters" } } }

যদি নাম প্রতি মালিকের জন্য ইউনিক এবং সার্ভিস একটি বিদ্যমান প্রজেক্ট পায়, 409 Conflict রিটার্ন করুন:

{ "error": { "code": "PROJECT_NAME_TAKEN", "message": "Project name already exists", "details": { "name": "Roadmap" } } }

একটি সিদ্ধান্ত যা প্যাটার্ন পরিষ্কার রাখে: হ্যান্ডলার চেক করে "এই অনুরোধটি সঠিকভাবে শেইপ করা আছে কি?" আর সার্ভিস মালিক হয় "এটি অনুমোদিত কি?"। এই বিভাজন জেনারেট হওয়া এন্ডপয়েন্টগুলোকে পূর্বানুমেয় করে।

সাধারণ ভুল যা সামঞ্জস্য ভেঙে দেয় (এবং সেগুলো কীভাবে এড়াবেন)

জেনারেটরকে ইম্প্রোভাইজ করতে দিলে দ্রুত সামঞ্জস্য হারিয়ে যায়।

একটি সাধারণ drift হল নতুন ত্রুটি শেইপ। এক এন্ডপয়েন্ট {error: "..."} রিটার্ন করে, অন্যটি {message: "..."}, আর তৃতীয়টি একটি নেস্টেড অবজেক্ট যোগ করে। এটিকে ঠিক করুন একটি একক ত্রুটি এনভেলপ এবং একটি স্ট্যাটাস কোড ম্যাপ রেখে এক জায়গায়, তারপর নতুন এন্ডপয়েন্টগুলোকে তা পুনঃব্যবহার করতে বাধ্য করুন। যদি জেনারেটর একটি নতুন ফিল্ড প্রস্তাব করে, সেটাকে API পরিবর্তনের অনুরোধ হিসেবে বিবেচনা করুন, কনভেনিয়েন্স হিসেবে নয়।

আরেকটি ড্রিফট হল হ্যান্ডলার ব্লোট। শুরুতে ছোট: validate, তারপর permission checks, তারপর DB query, তারপর ব্যবসায়িক শাখা। একেবারে দ্রুত প্রতিটি হ্যান্ডলার আলাদা দেখায়। একটি নিয়ম রাখুন: হ্যান্ডলার HTTP-কে টাইপ করা ইনপুট ও আউটপুটে ট্রান্সলেট করবে; সার্ভিস সিদ্ধান্তের মালিক; ডাটা অ্যাক্সেস কুয়েরির মালিক।

নামকরণ মিল না থাকাও সমস্যার কারণ। যদি এক এন্ডপয়েন্ট CreateUserRequest ব্যবহার করে এবং অন্যটি NewUserPayload, আপনি টাইপ খুঁজতে এবং গ্লু লেখাতে সময় নষ্ট করবেন। একটি নামকরণ স্কিম বেছে নিন এবং নতুন নাম প্রত্যাখ্যান করুন যদি না একটু জোরালো কারণ থাকে।

কখনো ক্লায়েন্টকে কাঁচা ডাটাবেস এরর রিটার্ন করবেন না। অন্তর্সংগীতি লিক করা ছাড়া, এটি বিভিন্ন এন্ডপয়েন্টে অনিয়মিত মেসেজ এবং স্ট্যাটাস কোড তৈরি করে। অভ্যন্তরীণ ত্রুটিকে ওয়্যাপ করুন, কারণ লগে কারণটি রাখুন, এবং একটি স্থির পাবলিক এরর কোড রিটার্ন করুন।

"কেবল সুবিধার জন্য" নতুন লাইব্রেরি যোগ করা এড়িয়ে চলুন। প্রতিটি অতিরিক্ত ভ্যালিডেটর, রাউটার হেল্পার, বা এরর প্যাকেজ একটি অতিরিক্ত স্টাইল তৈরি করে মেলানো কঠিন করে তোলে।

বহু ভাঙনের প্রতিরোধক:

  • নতুন এন্ডপয়েন্টগুলোকে বিদ্যমান এরর টাইপ এবং হেল্পার পুনঃব্যবহার করতে বাধ্য করুন।
  • হ্যান্ডলারগুলো ব্যবসায়িক নিয়ম এবং ডাটাবেস অ্যাক্সেস মুক্ত রাখুন।
  • রিকোয়েস্ট ও রেসপন্স স্ট্রাক্টগুলোর জন্য একটি নামকরণ রীতি প্রয়োজনীয় করুন।
  • অভ্যন্তরীণ এররগুলো পাবলিক এরর কোডে ম্যাপ করুন, কখনো কাঁচা এরর নয়।
  • ডিপেনডেন্সি যোগ করুন কেবল স্পষ্ট, লিখিত কারণে।

যদি আপনি দুইটি এন্ডপয়েন্ট ডিফ করতে পারেন না এবং একই আকার দেখতে পান (ইম্পোর্ট, ফ্লো, এরর হ্যান্ডলিং), তাহলে প্রম্পট শক্ত করে পুনরায় জেনারেট করুন মর্জ করার আগে।

দ্রুত চেকলিস্ট জেনারেট হওয়া এন্ডপয়েন্ট মার্জ করার আগে

Lock in one API pattern
Turn your reference endpoint into repeatable templates for every new route.
Start Building

কিছু জেনারেট হওয়ার পরে মার্জ করার আগে স্ট্রাকচার প্রথমে চেক করুন। যদি আকার ঠিক থাকে, লজিক বাগ খুঁজে পাওয়া সহজ।

স্ট্রাকচার চেক:

  • Handler ফ্লো ধারাবাহিক: ইনপুট বাইন্ড, ভ্যালিডেট, সার্ভিস কল, ডোমেন এরর HTTP-এ ম্যাপ, রেসপন্স লেখা।
  • Service কোডে শুধুই ব্যবসায়িক নিয়ম: কোনো সরাসরি HTTP বা JSON কাজ নেই।
  • সাফল্য রেসপন্স আপনার হাউস স্টাইল মেনে চলে (সবার জায়গায় একটি শেয়ারড এনভেলপ না হলে সরাসরি JSON সবার জায়গায়)।
  • এরর রেসপন্সগুলি ইউনিফর্ম: একই JSON ফিল্ড, একই কোড, একই request_id আচরণ।
  • নামকরণ এবং অবস্থান বোরিং দেখায়: ফাইল নাম, ফাংশন নাম, এবং রুট নাম বিদ্যমান এন্ডপয়েন্টের সাথে মেলে, এবং সবকিছু gofmt-এ ফরম্যাট করা আছে।

বিহেভিয়ার চেক:

  • টেস্ট চালান এবং নতুন হ্যান্ডলার/সার্ভিসের একটি ছোট টেস্ট যুক্ত করুন একটি নতুন ব্রাঞ্চের জন্য।
  • নিশ্চিত করুন ভ্যালিডেশন ব্যর্থতা একই কোড এবং স্ট্যাটাস দেয় যত অন্যান্য এন্ডপয়েন্ট।
  • একটি পরিচিত সার্ভিস এরর (যেমন "not found" বা "conflict") ট্রিগার করে HTTP স্ট্যাটাস এবং JSON শেইপ নিশ্চিত করুন।
  • কপি-পেস্ট বাকি অংশ সেন্টিনেল করুন: ভুল রুট পাথ, ভুল লগ মেসেজ, মিসম্যাচ DTO নাম ইত্যাদি।
  • সার্ভার লোকাল চালিয়ে ও বিল্ড করে দেখুন ওয়্যারিং এবং ইম্পোর্ট ঠিক আছে কিনা।

পরবর্তী ধাপ: প্যাটার্ন স্ট্যান্ডার্ডাইজ করুন, তারপর নিরাপদভাবে জেনারেশন বাড়ান

আপনার প্যাটার্নকে একটি শেয়ারড কনট্রাক্ট হিসেবে বিবেচনা করুন, পছন্দ নয়। "কীভাবে আমরা এন্ডপয়েন্ট তৈরি করি" ডকোডটি কোডের পাশে রাখুন এবং একটি রেফারেন্স এন্ডপয়েন্ট রাখুন যা পুরো অ্যাপ্রোচ দেখায়।

জেনারেশন ছোট ব্যাচে স্কেল করুন। বিভিন্ন ধরনের এজ পরীক্ষা করে 2–3 এন্ডপয়েন্ট জেনারেট করুন (একটা সহজ রিড, একটি ভ্যালিডেশন সহ ক্রিয়েট, একটি আপডেট যার নট-ফাউন্ড কেস আছে)। তারপর থামুন এবং সূক্ষ্ম করুন। যদি রিভিউগুলো একই স্টাইল ড্রিফট বারবার খুঁজে পায়, প্রথমে বেসলাইন ডক ও রেফারেন্স এন্ডপয়েন্ট আপডেট করুন তারপর আরো জেনারেট করুন।

আপনি পুনরাবৃত্তি করতে পারেন এমন একটি লুপ:

  • বেসলাইন লিখুন: ফাইল নাম, ফাংশন নাম, রিকোয়েস্ট/রেসপন্স স্ট্রাক্ট, এরর কোড, এবং ভ্যালিডেশন কোথায় হয় তা নির্ধারণ করুন।
  • একটি "গোল্ডেন" এন্ডপয়েন্ট রাখুন, এবং প্যাটার্ন বদলালে সেটি প্রথমে আপডেট করুন।
  • কিছু এন্ডপয়েন্ট ব্যাচে জেনারেট করুন, সামঞ্জস্যের জন্য রিভিউ করুন, তারপর প্রম্পট এবং প্যাটার্ন ডক ঠিক করুন।
  • পুরোনো এন্ডপয়েন্টগুলো কুচি কুচি করে রিফ্যাক্টর করুন এবং যদি আচরণ বদলে যায় তবে রোলব্যাক পথ রাখুন।
  • এক সপ্তাহের জন্য একটি মেট্রিক ট্র্যাক করুন: একটি এন্ডপয়েন্ট যোগ করতে সময়, মর্জ পরবর্তী বাগ হারের, বা রিভিউ টাইম।

যদি আপনি একটি শক্ত বাঁধা-বিচার লুপ চান, Koder.ai (koder.ai) মতো একটি vibe-coding প্ল্যাটফর্ম আপনাকে চ্যাট-চালিত ওয়ার্কফ্লোতে দ্রুত স্ক্যাফোল্ড এবং ইটারেট করতে সাহায্য করতে পারে, তারপর যখন এটি আপনার স্ট্যান্ডার্ডের সাথে মিলে যায় তখন সোর্স কোড এক্সপোর্ট করুন। টুলের তুল্য কম গুরুত্বপূর্ণ—নিয়মটাই মূল।

সাধারণ প্রশ্ন

What’s the fastest way to stop a Go API from getting inconsistent?

Lock down a repeatable template early: a consistent layer split (handler → service → data access), one error envelope, and a status-code map. Then use a single reference endpoint as the example every new endpoint must copy.

What should a handler do (and not do)?

Keep handlers HTTP-only:

  • Bind/parse the request
  • Do basic “shape validation” (required fields, simple formats)
  • Call the service
  • Map typed errors to HTTP status codes
  • Write JSON using shared helpers

If you see SQL, permission checks, or business branching in a handler, push that into the service.

What belongs in the service layer?

Put business rules and decisions in the service:

  • Permissions and access rules
  • Invariants (state transitions, uniqueness rules, “allowed” checks)
  • Orchestration across repositories and external calls

The service should return domain results and typed errors—no HTTP status codes, no JSON shaping.

What belongs in the data access/repository layer?

Keep persistence concerns isolated:

  • SQL/queries and transactions
  • Mapping rows to structs
  • Returning storage errors (that the service can interpret)

Avoid encoding API response formats or enforcing business rules in the repo beyond basic data integrity.

Where should validation live?

A simple default:

  • Handlers validate request shape (missing fields, basic format)
  • Services validate meaning (permissions, invariants, state)

Example: handler checks email is present and looks like an email; service checks it’s allowed and not already in use.

What should a standard API error response look like?

Use one standard error envelope everywhere and keep it stable. A practical shape is:

  • code for machines (stable)
  • message for humans (short and safe)
  • details for structured extras (like field errors)
  • request_id for tracing

This avoids client-side special cases and keeps generated endpoints predictable.

How do I choose between 400 vs 422 vs 409 for errors?

Write down a status-code map and follow it every time. A common split:

  • 400 for malformed JSON (bad_json)
  • 422 for validation failures (validation_failed)
  • 404 for missing resources (not_found)
  • 409 for conflicts (duplicates/version mismatches)
  • 500 for unexpected failures

The key is consistency: no debating per endpoint.

Should I ever return raw database errors to clients?

Return safe, consistent public errors, and log the real cause internally.

  • Response: stable code, short message, plus request_id
  • Logs: full error details (SQL errors, upstream payloads, user IDs)

This prevents leaking internals and avoids random error message differences across endpoints.

What is a reference endpoint, and why do I need one?

Create one “golden” endpoint you trust and require new endpoints to match it:

  • Same flow (bind → validate → service → error map → JSON)
  • Same helpers (BindJSON, WriteJSON, WriteError, etc.)
  • Same folder layout and naming

Then add a couple of small tests (even table tests for error mapping) to lock the pattern in.

How do I prompt Claude to generate new endpoints without breaking my structure?

Give the model strict context and constraints:

  • Paste the reference endpoint and the pattern rules
  • Specify route, request/response JSON examples, and error cases
  • List exactly which files it may output
  • Explicitly say what it must not change (router setup, error format, helpers)

After generation, reject diffs that “improve” architecture instead of following the baseline.

সূচিপত্র
কেন Go API বিশৃঙ্খল হয় যখন প্যাটার্নগুলো আগে স্থির করা না থাকেএক লেয়ার বিভাজন বাছাই করুন: handler, service, এবং data accessএকটি স্ট্যান্ডার্ড ত্রুটি রেসপন্স এবং স্ট্যাটাস কোড ম্যাপ নির্ধারণ করুনফোল্ডার লেআউট ও নামকরণ যা জেনারেশনকে পূর্বানুমেয় করেএকটি রেফারেন্স এন্ডপয়েন্ট তৈরি করুন যা প্যাটার্ন নির্ধারণ করেধাপে ধাপে: Claude কে একটি নতুন এন্ডপয়েন্ট তৈরি করতে বলুন যাতে তা ম্যাচ করেএকটি পুনরায় ব্যবহারযোগ্য প্রম্পট টেমপলেট অনুগত এন্ডপয়েন্ট স্ক্যাফোল্ডিংয়ের জন্যবাস্তবসম্মত উদাহরণ: স্টাইল ভাঙা ছাড়াই একটি Create এন্ডপয়েন্ট যোগ করাসাধারণ ভুল যা সামঞ্জস্য ভেঙে দেয় (এবং সেগুলো কীভাবে এড়াবেন)দ্রুত চেকলিস্ট জেনারেট হওয়া এন্ডপয়েন্ট মার্জ করার আগেপরবর্তী ধাপ: প্যাটার্ন স্ট্যান্ডার্ডাইজ করুন, তারপর নিরাপদভাবে জেনারেশন বাড়ানসাধারণ প্রশ্ন
শেয়ার