কম্পিউটার টিউটোরিয়াল

Go ওয়েব ডেভেলপমেন্ট মাস্টারি: মিডলওয়্যার, টেমপ্লেটিং, ডেটাবেস ও আরও

এই সিরিজের পূর্ববর্তী আর্টিকেলে, আমরা Go net/http প্যাকেজ এবং প্রোডাকশন-রেডি ওয়েব অ্যাপ্লিকেশনে এর ব্যবহার নিয়ে বিস্তারিত আলোচনা করেছি। আমরা মূলত রাউটিং দিক এবং http.ServeMux টাইপের অন্যান্য বৈশিষ্ট্য ও ফিচারগুলো নিয়ে ফোকাস করেছি।

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

Go-তে মিডলওয়্যার

অনেক বা সকল HTTP রিকুয়েস্টের জন্য chạy করার জরুরি শেয়ার্ড ফাংশনালিটি সেট আপ করার প্র্যাকটিসকে মিডলওয়্যার বলা হয়। কিছু অপারেশন, যেমন অথেন্টিকেশন, লগিং, এবং কুকি ভ্যালিডেশন, প্রায়ই মিডলওয়্যার ফাংশন হিসেবে ইমপ্লিমেন্ট করা হয়, যা রেগুলার রুট হ্যান্ডলারের আগে বা পরে একটি রিকুয়েস্টের ওপর স্বতন্ত্রভাবে কাজ করে।

Go-তে মিডলওয়্যার ইমপ্লিমেন্ট করতে, আপনাকে নিশ্চিত করতে হবে আপনার पास একটি টাইপ আছে যা http.Handler ইন্টারফেস স্যাটিসফাই করে। সাধারণত, এর মানে আপনাকে ServeHTTP(http.ResponseWriter, *http.Request) সিগনেচার olan একটি মেথড টাইপের সাথে আট্যাচ করতে হয়। এই মেথড ব্যবহার করলে, যেকোনো টাইপ http.Handler ইন্টারফেস স্যাটিসফাই করবে।

এখানে একটি সিম্পল উদাহরণ:

package main import "net/http" type helloHandler struct { name string } func (h helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello " + h.name)) } func main() { mux := http.NewServeMux() helloJohn := helloHandler{name: "John"} mux.Handle("/john", helloJohn) http.ListenAndServe(":8080", mux) } 

/john রুটে পাঠানো যেকোনো রিকুয়েস্ট সরাসরি helloHandler.ServeHTTP মেথডে যাবে। আপনি এটি একশনে দেখতে পারেন সার্ভার শুরু করে https://localhost:8080/john-এ যেতে।

http.Handler ইমপ্লিমেন্ট করার জন্য প্রতিবার কাস্টম টাইপে ServeHTTP মেথড যোগ করা খুব কষ্টসাধ্য, তাই net/http প্যাকেজ http.HandlerFunc টাইপ দিয়ে থাকে, যা সাধারণ ফাংশনকে HTTP হ্যান্ডলার হিসেবে ব্যবহার করার সুযোগ দেয়।

আপনাকে শুধু নিশ্চিত করতে হবে আপনার ফাংশনের সিগনেচার: func(http.ResponseWriter, *http.Request); তারপর এটাকে http.HandlerFunc টাইপে কনভার্ট করুন।

package main import "net/http" func helloJohnHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello John")) } func main() { mux := http.NewServeMux() mux.Handle("/john", http.HandlerFunc(helloJohnHandler)) http.ListenAndServe(":8080", mux) } 

আপনি main ফাংশনে mux.Handle লাইনটি mux.HandleFunc- দিয়ে রিপ্লেস করতে পারেন এবং ফাংশনটি সরাসরি পাস করতে পারেন। পূর্ববর্তী আর্টিকেলে আমরা এই প্যাটার্ন এক্সক্লूसিভলি ব্যবহার করেছি।

func main() { mux := http.NewServeMux() mux.HandleFunc("/john", helloJohnHandler) http.ListenAndServe(":8080", mux) } 

এই পয়েন্টে, নাম স্ট্রিং-এ হার্ডকোডেড, পূর্বের মতো নয় যখন আমরা main ফাংশনে হ্যান্ডলার কল করার আগে নাম সেট করতে পারতাম। এই লিমিটেশন সরাতে, আমরা হ্যান্ডলার লজিককে একটি ক্লোজারে রাখতে পারি, নিচের মতো:

package main import "net/http" func helloHandler(name string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello " + name)) }) } func main() { mux := http.NewServeMux() mux.Handle("/john", helloHandler("John")) http.ListenAndServe(":8080", mux) } 

helloHandler ফাংশন নিজে http.Handler ইন্টারফেস স্যাটিসফাই করে না, কিন্তু এটি একটি অ্যানোনিমাস ফাংশন তৈরি করে এবং রিটার্ন করে যা স্যাটিসফাই করে। এই ফাংশন name প্যারামিটারকে ক্লোজার করে, অর্থাৎ এটি যখনই কল হবে তখন সেটা অ্যাক্সেস করতে পারবে। এই পয়েন্টে, helloHandler ফাংশনটি আবার আবার ভিন্ন ভিন্ন নামের জন্য রিইউজ করা যায়।

তাহলে, এতে মিডলওয়্যারের সাথে কী সম্পর্ক? ঠিক উপরের মতোই একটি মিডলওয়্যার ফাংশন তৈরি করা হয়। উদাহরণে স্ট্রিং পাস করার বদলে, আমরা চেইনে পরবর্তী হ্যান্ডলারকে আর্গুমেন্ট হিসেবে পাস করতে পারি।

এখানে সম্পূর্ণ প্যাটার্ন:

func middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // মিডলওয়্যার লজিক এখানে... next.ServeHTTP(w, r) }) } 

উপরোক্ত middleware ফাংশন একটি হ্যান্ডলার গ্রহণ করে এবং একটি হ্যান্ডলার রিটার্ন করে। লক্ষ্য করুন কিভাবে আমরা অ্যানোনিমাস ফাংশনকে http.HandlerFunc টাইপে কাস্ট করে http.Handler ইন্টারফেস স্যাটিসফাই করাচ্ছি। অ্যানোনিমাস ফাংশনের শেষে, next.ServeHTTP() মেথড ইনভোক করে কন্ট্রোল next হ্যান্ডলারকে ট্রান্সফার করা হয়। আপনি যদি হ্যান্ডলারগুলোর মধ্যে ভ্যালু পাস করতে চান, যেমন অথেন্টিকেটেড ইউজারের আইডি, তবে Go 1.7-এ পরিচয়পত্রিত http.Request.Context() মেথড ব্যবহার করতে পারেন।

আসুন একটি মিডলওয়্যার ফাংশন লিখি যা শুধু এই প্যাটার্ন ডেমো করবে। এই ফাংশন রিকুয়েস্ট অবজেক্টে requestTime নামে একটি প্রপার্টি যোগ করবে, যা পরবর্তীতে helloHandler ব্যবহার করবে রিকুয়েস্টের টাইমস্ট্যাম্প দেখানোর জন্য।

package main import ( "context" "net/http" "time" ) func requestTime(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() ctx = context.WithValue(ctx, "requestTime", time.Now().Format(time.RFC3339)) r = r.WithContext(ctx) next.ServeHTTP(w, r) }) } func helloHandler(name string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { responseText := "<h1>Hello " + name + "</h1>" if requestTime := r.Context().Value("requestTime"); requestTime != nil { if str, ok := requestTime.(string); ok { responseText = responseText + "\n<small>Generated at: " + str + "</small>" } } w.Write([]byte(responseText)) }) } func main() { mux := http.NewServeMux() mux.Handle("/john", requestTime(helloHandler("John"))) http.ListenAndServe(":8080", mux) } 

Go ওয়েব ডেভেলপমেন্ট মাস্টারি: মিডলওয়্যার, টেমপ্লেটিং, ডেটাবেস ও আরও

যেহেতু আমাদের মিডলওয়্যার ফাংশন http.Handler টাইপ গ্রহণ করে এবং রিটার্ন করে, इसलিয়ে মিডলওয়্যার ফাংশনগুলোর একটি অনন্ত চেইন তৈরি করা সম্ভব যেগুলো একে অপরের ভেতর নেস্টেড।

উদাহরণস্বরূপ,

mux := http.NewServeMux() mux.Handle("/", middleware1(middleware2(appHandler))) 

আপনি Alice-এর মতো লাইব্রেরি ব্যবহার করে উপরের কনস্ট্রাক্টকে আরও রিডেবল ফর্মে রূপান্তর করতে পারেন:

alice.New(middleware1, middleware2).Then(appHandler) 

টেমপ্লেটিং

সিংগল-পেজ অ্যাপ্লিকেশনের আসার সাথে টেমপ্লেট ব্যবহারের জনপ্রিয়তা কমেছে, তবুও এটি একটি সম্পূর্ণ ওয়েব ডেভেলপমেন্ট সলিউশনের গুরুত্বপূর্ণ দিক।

Go আপনার সকল টেমপ্লেটিং দরকারের জন্য দুটি প্যাকেজ প্রদান করে: text/template এবং html/template। উভয়টির ইন্টারফেস একই, কিন্তু পরেরটি পেছনে কিছু এনকোডিং করে কোড ইনজেকশন এক্সপ্লয়েট থেকে রক্ষা করে।

যদিও Go টেমপ্লেটগুলো সবচেয়ে এক্সপ্রেসিভ নয়, তারা কাজ ঠিকমতো করে এবং প্রোডাকশন অ্যাপ্লিকেশনে ব্যবহার করা যায়। ফ্যাক্ট, হ্যুগো ( জনপ্রিয় স্ট্যাটিক সাইট জেনারেটর) এর টেমপ্লেটিং সিস্টেম এর ওপর ভিত্তি করে তৈরি।

চলুন দ্রুত দেখি html/template প্যাকেজ কীভাবে ব্যবহার করে HTML আউটপুট ওয়েব রিকুয়েস্টের রেসপন্স হিসেবে পাঠাতে হয়।

একটি টেমপ্লেট তৈরি করা

আপনার main.go ফাইল একই ডিরেক্টরিতে একটি index.html ফাইল তৈরি করুন এবং নিচের কোড যোগ করুন:

<ul> {{ range .TodoItems }} <li>{{ . }}</li> {{ end }} </ul> 

পরবর্তী, আপনার main.go ফাইলে নিচের কোড যোগ করুন:

package main import ( "html/template" "log" "os" ) func main() { t, err := template.ParseFiles("index.html") if err != nil { log.Fatal(err) } todos := []string{"Watch TV", "Do homework", "Play games", "Read"} err = t.Execute(os.Stdout, todos) if err != nil { log.Fatal(err) } } 

যদি আপনি উপরের প্রোগ্রাম go run main.go দিয়ে এক্সিকিউট করেন। আপনি নিচের আউটপুট দেখবেন:

<ul> <li>Watch TV</li> <li>Do homework</li> <li>Play games</li> <li>Read</li> </ul> 

অভিনন্দন! আপনি আপনার প্রথম Go টেমপ্লেট তৈরি করলেন। আমরা টেমপ্লেট ফাইলে যে সিনট্যাক্স ব্যবহার করেছি তার সংক্ষিপ্ত ব্যাখ্যা:

  • Go ডাবল ব্রেস ({{ এবং }}) ব্যবহার করে টেমপ্লেটে ডেটা ইভ্যালুয়েশন এবং কন্ট্রোল স্ট্রাকচার (যাকে অ্যাকশন বলা হয়) ডিলিমিট করে।
  • range অ্যাকশন হলো কীভাবে আমরা ডেটা স্ট্রাকচার (যেমন স্লাইস) ওভার ইটারেট করি।
  • . বর্তমান কনটেক্সটকে রিপ্রেজেন্ট করে। range অ্যাকশনে, বর্তমান কনটেক্সট হলো todos স্লাইস। ব্লকের ভেতরে, {{ . }} স্লাইসের প্রতিটি এলিমেন্টকে রিপ্রেজেন্ট করে।

main.go ফাইলে, template.ParseFiles মেথড এক বা একাধিক ফাইল থেকে একটি নতুন টেমপ্লেট তৈরি করতে ব্যবহৃত হয়। এই টেমপ্লেট後ে template.Execute মেথড দিয়ে এক্সিকিউট করা হয়; এটি একটি io.Writer এবং ডেটা নেয়, যা টেমপ্লেটে অ্যাপ্লাই হবে।

উপরের উদাহরণে, টেমপ্লেট স্ট্যান্ডার্ড আউটপুট-এ এক্সিকিউট হয়েছে, কিন্তু আমরা যেকোনো ডেস্টিনেশনে এক্সিকিউট করতে পারি, যতক্ষণ না সেটি io.Writer ইন্টারফেস স্যাটিসফাই করে। উদাহরণস্বরূপ, আপনি আউটপুট ওয়েব রিকুয়েস্টের অংশ হিসেবে রিটার্ন করতে চাইলে, শুধু টেমপ্লেটকে ResponseWriter ইন্টারফেস-এ এক্সিকিউট করলেই হবে, নিচের মতো:

package main import ( "html/template" "log" "net/http" ) func main() { t, err := template.ParseFiles("index.html") if err != nil { log.Fatal(err) } todos := []string{"Watch TV", "Do homework", "Play games", "Read"} http.HandleFunc("/todos", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") err = t.Execute(w, todos) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }) http.ListenAndServe(":8080", nil) } 

Go ওয়েব ডেভেলপমেন্ট মাস্টারি: মিডলওয়্যার, টেমপ্লেটিং, ডেটাবেস ও আরও

এই সেকশনটি শুধু Go-এর টেমপ্লেট প্যাকেজের একটি দ্রুত ইন্ট্রো। আপনি যদি আরও জটিল ইউজ কেসে আগ্রহী হন, তবে text/template এবং html/template-এর ডকুমেন্টেশন চেক আউট করতে ভুলবেন না।

আপনি যদি Go-এর টেমপ্লেটিং পছন্দ না করেন, তবে বিকল্প রয়েছে, যেমন Plush লাইব্রেরি।

JSON-এর সাথে কাজ করা

আপনি যদি JSON অবজেক্টের সাথে কাজ করতে চান, তবে খুশির খবর হলো Go-এর স্ট্যান্ডার্ড লাইব্রেরিতে JSON পার্স এবং এনকোড করার জন্য সবকিছু রয়েছে encoding/json প্যাকেজের মাধ্যমে।

ডিফল্ট টাইপস

Go-তে JSON অবজেক্ট এনকোড বা ডিকোড করার সময়, নিচের টাইপগুলো ব্যবহৃত হয়:

  • bool JSON বুলিয়ানের জন্য,
  • float64 JSON নম্বরের জন্য,
  • string JSON স্ট্রিং-এর জন্য,
  • nil JSON null-এর জন্য,
  • map[string]interface{} JSON অবজেক্টের জন্য, এবং
  • []interface{} JSON অ্যারে-এর জন্য।

এনকোডিং

একটি ডেটা স্ট্রাকচার JSON হিসেবে এনকোড করতে json.Marshal ফাংশন ব্যবহার করা হয়। উদাহরণ:

package main import ( "encoding/json" "fmt" ) type Person struct { FirstName string LastName string Age int email string } func main() { p := Person{ FirstName: "Abraham", LastName: "Freeman", Age: 100, email: "abraham.freeman@hey.com", } json, err := json.Marshal(p) if err != nil { fmt.Println(err) return } fmt.Println(string(json)) } 

উপরের প্রোগ্রামে, আমাদের একটি Person স্ট্রাক্ট আছে চারটি ভিন্ন ফিল্ডসহ। main ফাংশনে, Person-এর একটি ইনস্ট্যান্স তৈরি করা হয়েছে সকল ফিল্ড ইনিশিয়ালাইজ করে। json.Marshal মেথডটি p স্ট্রাকচারকে JSON-এ কনভার্ট করতে ব্যবহৃত হয়। এই মেথড একটি বাইট স্লাইস বা এরর রিটার্ন করে, যা হ্যান্ডেল করতে হয় JSON ডেটা এক্সেস করার আগে।

Go-তে বাইট স্লাইসকে স্ট্রিংএ কনভার্ট করতে টাইপ কনভার্সন করতে হয়, উপরের মতো। এই প্রোগ্রাম রান করলে নিচের আউটপুট আসবে:

{"FirstName":"Abraham","LastName":"Freeman","Age":100} 

আপনি দেখছেন, আমরা একটি বৈধ JSON অবজেক্ট পাচ্ছি যা যেকোনোভাবে ব্যবহার করা যায়। লক্ষ্য করুন email ফিল্ডটি রেজাল্টে নেই। এর কারণ এটি Person অবজেক্ট থেকে এক্সপোর্টেড নয় কারণ এটি স্মল লেটার দিয়ে শুরু হয়।

ডিফল্টভাবে, Go স্ট্রাক্টের প্রপার্টি নামগুলো JSON অবজেক্টের ফিল্ড নাম হিসেবে ব্যবহার করে। তবে এটি স্ট্রাক্ট ফিল্ড ট্যাগ দিয়ে পরিবর্তন করা যায়।

type Person struct { FirstName string `json:"first_name"` LastName string `json:"last_name"` Age int `json:"age"` email string `json:"email"` } 

উপরের স্ট্রাক্ট ফিল্ড ট্যাগগুলো স্পেসিফাই করে যে JSON এনকোডার স্ট্রাক্টের FirstName প্রপার্টিকে JSON অবজেক্টের first_name ফিল্ডে ম্যাপ করবে এবং এভাবেই অন্যগুলো। পূর্বের উদাহরণে এই পরিবর্তন নিচের আউটপুট দেবে:

{"first_name":"Abraham","last_name":"Freeman","age":100} 

ডিকোডিং

json.Unmarshal ফাংশন একটি JSON অবজেক্টকে Go স্ট্রাক্টে ডিকোড করতে ব্যবহৃত হয়। এর সিগনেচার:

func Unmarshal(data []byte, v interface{}) error 

এটি JSON ডেটার একটি বাইট স্লাইস এবং ডিকোড করা ডেটা স্টোর করার জায়গা নেয়। যদি ডিকোডিং সফল হয়, তবে রিটার্ন করা এরর nil হবে।

আমরা যদি নিচের JSON অবজেক্ট থাকে,

json := "{"first_name":"John","last_name":"Smith","age":35, "place_of_birth": "London", gender:"male"}" 

তবে আমরা এটাকে Person স্ট্রাক্টের একটি ইনস্ট্যান্সে ডিকোড করতে পারি, নিচের মতো:

func main() { b := `{"first_name":"John","last_name":"Smith","age":35, "place_of_birth": "London", "gender":"male", "email": "john.smith@hmail.com"}` var p Person err := json.Unmarshal([]byte(b), &p) if err != nil { fmt.Println(err) return } fmt.Printf("%+v\n", p) } 

এবং আপনি নিচের আউটপুট পাবেন:

{FirstName:John LastName:Smith Age:35 email:} 

Unmarshal শুধু সেস ফিল্ডগুলো ডিকোড করে যা ডেস্টিনেশন টাইপে পাওয়া যায়। এই কেসে, place_of_birth এবং gender ইগ্নোর হয়েছে কারণ সেগুলো Person-এ কোনো স্ট্রাক্ট ফিল্ডে ম্যাপ হয়নি। এই বিহевиয়র বড় JSON অবজেক্ট থেকে কিছু নির্দিষ্ট ফিল্ড পিক করার জন্য কাজে লাগতে পারে। পূর্বের মতো, ডেস্টিনেশন স্ট্রাক্টের অনএক্সপোর্টেড ফিল্ডগুলো অপ্রভাবিত থাকে যদি JSON অবজেক্টে সেসপective ফিল্ড থাকে। তাই email আউটপুটে খালি স্ট্রিং রয়েছে যদিও JSON অবজেক্টে এটি উপস্থিত ছিল।

ডেটাবেস

database/sql প্যাকেজ SQL (অথবা SQL-লাইক) ডেটাবেসের চারপাশে একটি জেনেরিক ইন্টারফেস প্রদান করে। এটি অবশ্যই একটি ডেটাবেস ড্রাইভারসহ ব্যবহার করতে হয়, যেমন এখানে লিস্ট করা হয়েছে। ডেটাবেস ড্রাইভার ইমপোর্ট করার সময়, আপনাকে এর সামনে আন্ডারস্কোর _ দিয়ে প্রিফিক্স করতে হয় যাতে এটি ইনিশিয়ালাইজ হয়।

উদাহরণস্বরূপ, database/sql-এর সাথে MySQL ড্রাইভার প্যাকেজ কীভাবে ব্যবহার করতে হয়:

import ( "database/sql" _ "github.com/go-sql-driver/mysql" ) 

হুডের নিচে, ড্রাইভার নিজেকে database/sql প্যাকেজে উপলব্ধ হিসেবে রেজিস্টার করে, কিন্তু এটি সরাসরি আমাদের কোডে ব্যবহার হবena। এটি আমাদের একটি নির্দিষ্ট ড্রাইভারের ওপর ডিপেন্ডেন্সি কমাতে সাহায্য করে যাতে তা কম 노력েই অন্য ড্রাইভারসহ স্ব্যাপ করা যায়।

ডেটাবেস কানেকশন খোলা

ডেটাবেস এক্সেস করতে, আপনাকে একটি sql.DB অবজেক্ট তৈরি করতে হবে, নিচের মতো:

func main() { db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/hello") if err != nil { log.Fatal(err) } } 

sql.Open মেথড ডেটাবেস অ্যাবস্ট্রাকশনকে পরবর্তী ব্যবহারের জন্য প্রস্তুত করে। এটি ডেটাবেসের সাথে কানেকশন স্থাপন করে না বা কানেকশন প্যারামিটার ভ্যালিডেট করে না। আপনি যদি অবিলম্বে নিশ্চিত করতে চান যে ডেটাবেস উপলব্ধ এবং অ্যাক্সেসযোগ্য, তবে db.Ping() মেথড ব্যবহার করুন:

err = db.Ping() if err != nil { log.Fatal(err) } 

ডেটাবেস কানেকশন বন্ধ করা

ডেটাবেস কানেকশন বন্ধ করতে, আপনি db.Close() ব্যবহার করতে পারেন। সাধারণত, আপনি ডেটাবেস বন্ধ করার কাজ defer করবেন যতক্ষণ না ডেটাবেস কানেকশন খোলা ফাংশনটি শেষ হয়, সাধারণত main ফাংশন:

func main() { db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/hello") if err != nil { log.Fatal(err) } defer db.Close() } 

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

ডেটাবেস থেকে ডেটা ফেচ করা

এক টেবিল কোয়েরি করা তিন স্টেপে করা যায়। প্রথম, db.Query() কল করুন। তারপর, রোগুলোর ওভার ইটারেট করুন। শেষে, rows.Scan() ব্যবহার করে প্রতিটি রো ভেরিয়েবলে এক্সট্রাক্ট করুন। উদাহরণ:

var ( id int name string ) rows, err := db.Query("select id, name from users where id = ?", 1) if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { err := rows.Scan(&id, &name) if err != nil { log.Fatal(err) } log.Println(id, name) } err = rows.Err() if err != nil { log.Fatal(err) } 

যদি একটি কোয়েরি সিংগল রো রিটার্ন করে, তবে আপনি db.QueryRow মেথড ব্যবহার করতে পারেন db.Query-র বদলে এবং পূর্বের কোড স্নিপেটের দীর্ঘ বয়লারপ্লেট কোড এড়াতে পারেন:

var ( id int name string ) err = db.QueryRow("select id, name from users where id = ?", 1).Scan(&id, &name) if err != nil { log.Fatal(err) } fmt.Println(id, name) 

NoSQL ডেটাবেস

Go-তে NoSQL ডেটাবেসের জন্যও ভালো সাপোর্ট রয়েছে, যেমন Redis, MongoDB, Cassandra, এবং অন্যান্য, কিন্তু এটি তাদের সাথে কাজ করার জন্য কোনো স্ট্যান্ডার্ড ইন্টারফেস দেয় না। আপনাকে সম্পূর্ণরূপে নির্দিষ্ট ডেটাবেসের ড্রাইভার প্যাকেজের ওপর নির্ভর করতে হবে। কিছু উদাহরণ নিচে দেওয়া হলো:

  • https://github.com/go-redis/redis (Redis ড্রাইভার)।
  • https://github.com/mongodb/mongo-go-driver (MongoDB ড্রাইভার)।
  • https://github.com/gocql/gocql (Cassandra ড্রাইভার)।
  • https://github.com/Shopify/sarama (Apache Kafka ড্রাইভার)

সমাপনী

এই আর্টিকেলে, আমরা Go-তে ওয়েব অ্যাপ্লিকেশন বানানোর কিছু অপরিহার্য দিক নিয়ে আলোচনা করেছি। এখন আপনাকে বুঝতে পারা উচিত কেন অনেক Go প্রোগ্রামার স্ট্যান্ডার্ড লাইব্রেরির কসম খায়। এটি খুব কম্প্রيهেনসিভ এবং প্রোডাকশন-রেডি সার্ভিসের জন্য প্রয়োজনীয় অধিকাংশ টুল প্রদান করে।

আমরা এখানে যা কভার করেছি তার কোনো বিষয়ে ক্লেরিফিকেশন দরকার হলে, টুইটারে আমাকে মেসেজ পাঠান। এই সিরিজের পরের এবং চূড়ান্ত আর্টিকেলে, আমরা go টুল এবং Go-তে ডেভেলপমেন্টের সময় সাধারণ টাস্কগুলো tackle করার জন্য এর ব্যবহার নিয়ে আলোচনা করব।

পড়ার জন্য ধন্যবাদ, এবং 해পি কোডিং!

  1. Chrome-এ ওয়েব ডেভেলপমেন্টের জন্য ১১টি সেরা এক্সটেনশন

  2. মাস্টারিং ওয়েব স্ক্র্যাপিং: পডকাস্ট ডেটা এক্সট্র্যাকশনের ধাপে ধাপে গাইড – পার্ট ৩

  3. চ্যাটবট: ওয়েব ও অ্যাপ ডেভেলপমেন্টে বিপ্লব

  4. ব্লুফিশ ও কম্পোজার দিয়ে ওয়েব ডেভেলপমেন্ট সহজ করুন: নতুনদের গাইড