1 ইন্টারফেসের পরিচিতি

1.1 ইন্টারফেস কি

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

// একটি ইন্টারফেস সংজ্ঞা করুন
type Reader interface {
    Read(p []byte) (n int, err error)
}

এই Reader ইন্টারফেসে, যেকোনো ধরণের কিছু যিনি Read(p []byte) (n int, err error) মেথডটি সংজ্ঞা করে সেই কিছুক্ষণেই Reader ইন্টারফেসটি সংজ্ঞা করে।

2 ইন্টারফেসের সংজ্ঞা

2.1 ইন্টারফেসের সিনট্যাক্স গঠন

Go ভাষায়, ইন্টারফেসের সংজ্ঞা নিম্নলিখিত হতে হয়:

type interfaceName interface {
    methodName(parameterList) returnTypeList
}
  • interfaceName: ইন্টারফেসের নাম Go ভাষার নামকরণ অনুসারে সরবরাহ করতে হয়, এটি একটি বড় অক্ষর দিয়ে শুরু হয়।
  • methodName: ইন্টারফেসের প্রয়োজনীয় মেথডের নাম।
  • parameterList: মেথডের প্যারামিটার তালিকা, প্যারামিটারগুলি কমা দ্বারা পৃথক করা হয়।
  • returnTypeList: মেথডের ফেরতের প্রকারের তালিকা।

যদি একটি ধরণ সমস্ত মেথড সংজ্ঞা করে, তবে এই ধরণটি অবশ্যই সেই ইন্টারফেস সংজ্ঞা করে।

type Worker interface {
    Work()
    Rest()

উপরের Worker ইন্টারফেসে, যেকোনো ধরণের Work() এবং Rest() মেথড সংজ্ঞা করে সে Worker ইন্টারফেসটি পূরন করে।

3 ইন্টারফেস প্রযোজনীয় মেথড সমূহ

3.1 ইন্টারফেস প্রয়োজনীয় মেথড প্রয়োজনীয় নিয়মগুলি

Go ভাষায়, যদি একটি ধরণ মাত্র ইন্টারফেসের সমস্ত মেথড সংজ্ঞা করে, তবে এই ধরণটি সেই ইন্টারফেস পূরন করে বিবেচনা করতে হয়। এই বাস্তবায়ন স্বত: বা অভিন্যোত্রী। সে অতএব অভিন্যোত্রী ঠিক যে ধরণের উপাধান ঘোষণা করে এই মেথডগুলি পূরন করতে হবে। ইন্টারফেস চালিত করার নিয়মগুলি হল:

  • ইন্টারফেস পূরণ করা টাইপ হতে পারে একটি গঠিত বা অন্য কোনও প্রযুক্তি।
  • প্রযোজনীয় মেথডগুলি পূরন করার জন্য একটি ধরণ অবশ্যই সমস্ত ইন্টারফেস মেথড পূরণ করতে হবে।
  • ইন্টারফেসে মেথডগুলিতে সরাসরি এবং ইন্টারফেস মেথ

4.2 ইন্টারফেসের আবেদন পরিস্থিতি

ইন্টারফেসগুলি গো ভাষায় প্রচলিত। এখানে কিছু প্রধান আবেদনের উদাহরণ দেওয়া হল:

  • প্রধান লাইব্রেরিতে ইন্টারফেস: উদাহরণস্বরূপ, io.Reader এবং io.Writer ইন্টারফেসগুলি ফাইল প্রসেসিং এবং নেটওয়ার্ক প্রোগ্রামিং জন্য প্রযোজ্য।
  • সর্টিং: sort.Interface ইন্টারফেসে Len(), Less(i, j int) bool এবং Swap(i, j int) মেথডগুলি ইমপ্লিমেন্ট করলে যে কোনও কাস্টম স্লাইস সর্ট করার সুযোগ থাকে।
  • HTTP হ্যান্ডলার: http.Handler ইন্টারফেসে ServeHTTP(ResponseWriter, *Request) মেথড ইমপ্লিমেন্ট করলে কাস্টম HTTP হ্যান্ডলার তৈরির সুযোগ থাকে।

এখানে সর্টিং এর জন্য ইন্টারফেস ব্যবহারের একটি উদাহরণ:

package main

import (
    "fmt"
    "sort"
)

type AgeSlice []int

func (a AgeSlice) Len() int           { return len(a) }
func (a AgeSlice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a AgeSlice) Less(i, j int) bool { return a[i] < a[j] }

func main() {
    ages := AgeSlice{45, 26, 74, 23, 46, 12, 39}
    sort.Sort(ages)
    fmt.Println(ages) // আউটপুট: [12 23 26 39 45 46 74]
}

উপরের উদাহরণে, sort.Interface এর তিনটি মেথড ইমপ্লিমেন্ট করে, আমরা AgeSlice স্লাইস সর্ট করতে পারি, যা দেখায় যে ইন্টারফেস এর ক্ষমতা বিদ্যমান টাইপগুলির ব্যবহার প্রসারিত করতে পারে।

5 ইন্টারফেসের উন্নত বৈশিষ্ট্যগুলি

5.1 খালি ইন্টারফেস এবং তার প্রয়োজন

গো ভাষায়, খালি ইন্টারফেস হল একটি বিশেষ ইন্টারফেস ধরন যা কোনও মেথড ধারণ করেনা। অতএব, প্রায় যেকোনও প্রকারের মান খালি ইন্টারফেস হিসেবে গণ্য করা যেতে পারে। খালি ইন্টারফেসটি interface{} দিয়ে প্রদর্শিত হয় এবং গোতে এটি অত্যন্ত লক্ষ্যহীন ধরণ হিসেবে বহু গুরুত্বপূর্ণ ভূমিকা পালন করে।

// একটি খালি ইন্টারফেস সংজ্ঞায়িত করুন
var any interface{}

ডায়নামিক টাইপ বিচার:

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

func PrintAnything(v interface{}) {
    fmt.Println(v)
}

func main() {
    PrintAnything(123)
    PrintAnything("hello")
    PrintAnything(struct{ name string }{name: "Gopher"})
}

উপরের উদাহরণে, PrintAnything ফাংশনটি খালি ইন্টারফেস টাইপ v এবং এটি প্রিন্ট করে। PrintAnything সংখ্যা, স্ট্রিং বা স্ট্রাক্চার পাল্টানোর ক্ষমতা আছে।

5.2 ইন্টারফেস এমবেডিং

ইন্টারফেস এমবেডিং অন্য ইন্টারফেসের সমস্ত মেথডগুলি সংগ্রাহীত করা, এবং সম্ভাবনা অনুযায়ী কিছু নতুন মেথড যুক্ত করা বোঝায়। ইন্টারফেস সংজ্ঞানের মাধ্যমে এটি অর্জন করা হয়।

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

// ReadWriter ইন্টারফেস রিডার ইন্টারফেস এবং রাইটার ইন্টারফেস এমবেড করে
type ReadWriter interface {
    Reader
    Writer
}

ইন্টারফেস এমবেডিং ব্যবহার করে, আমরা একটি আরও বহুপরিপূর্ণ এবং হায়ারারকী ইন্টারফেস কাঠামো গড়তে পারি। এই উদাহরণে, ReadWriter ইন্টারফেসটি Reader এবং Writer ইন্টারফেসগুলির মেথডগুলিকে ধরে নেয়, পড়া এবং লিখার ক্ষমতা মিশ্রণ সাধন করে।

5.3 ইন্টারফেস টাইপ এসারশন

টাইপ এসারশন হল ইন্টারফেস টাইপ মানগুলোর চেক এবং রূপান্তর করার অপারেশন। যখন আমাদের কোনও ইন্টারফেস টাইপ মান থেকে একটি নির্দিষ্ট প্রকারের মান বের করতে হয়, তখন টাইপ এসারশন অত্যন্ত দরকারী হয়।

বিজ্ঞাপনের ধারণা:

value, ok := interfaceValue.(Type)

যদি এসারশনটি সফল হয়, তবে value হবে অন্যুন্দান প্রকারের মান Type এবং ok হবে true। যদি এসারশনটি ব্যর্থ হয়, তবে value হবে প্রকার Type এর শূন্য মান এবং ok হবে false

var i interface{} = "hello"

// টাইপ এসারশন
s, ok := i.(string)
if ok {
    fmt.Println(s) // আউটপুট: hello
}

// বাস্তব প্রকারের এসারশন
f, ok := i.(float64)
if !ok {
    fmt.Println("এসারশন ব্যার্থ হয়েছে!") // আউটপুট: এসারশন ব্যার্থ হয়েছে!
}

অ্যাপ্লিকেশন পরিস্থিতি:

টাইপ এসারশন সাধারণত ব্যবহার করা হয় খালি ইন্টারফেস interface{} এর মানের প্রকার নির্ধারণ করতে এবং এসারশনের ক্ষেত্রে, নির্দিষ্ট ইন্টারফেস ইমপ্লিমেন্ট করে প্রকার উপস্থাপন করতে।

5.4 ইন্টারফেস এবং বহুরূপতা

বহুরূপতা অবজেক্ট-উদ্যোগী প্রোগ্রামিংয়ে একটি মৌলিক ধারণা, যা বিভিন্ন ডেটা প্রকারকে নির্দিষ্ট প্রকারগুলির সম্পর্কে চিন্তা না করে একই একই ভাবে প্রসেস করার মাধ্যমে সম্পাদিত করে। গো ভাষায়, ইন্টারফেস বহুরূপতা অর্জনের জন্য মূল উপায়।

ইন্টারফেস দ্বারা বহুরূপতা পার্থক্য

type Shape interface {
    Area() float64
}

type Rectangle struct {
    Width, Height float64
}

type Circle struct {
    Radius float64
}

// রেক্ট্যাংগল ইন্টারফেস অনুমোদন দেয়
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// সার্কেল ইন্টারফেস অনুমোদন দেয়
func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

// বিভিন্ন আকৃতির আয়তন নির্ণয়
func CalculateArea(s Shape) float64 {
    return s.Area()
}

func main() {
    r := Rectangle{Width: 3, Height: 4}
    c := Circle{Radius: 5}
    
    fmt.Println(CalculateArea(r)) // আউটপুট: আয়তনের ক্ষেত্রফল
    fmt.Println(CalculateArea(c)) // আউটপুট: বৃত্তের ক্ষেত্রফল
}

এই উদাহরণে, Shape ইন্টারফেসটি বিভিন্ন আকৃতির জন্য একটি Area মেথড সংজ্ঞা করে। Rectangle এবং Circle সাংক্রান্তিক প্রকারগুলি এই ইন্টারফেস অনুমোদন করে, অর্থাৎ এই প্রকারগুলির ক্ষমতা আয়তন নির্ণয় করার ক্ষমতা আছে। CalculateArea ফাংশনটি একটি Shape ইন্টারফেস ধরে প্যারামিটার নিয়ে এবং যে কোনও আকৃতির ক্ষেত্রফল নির্ণয় করতে পারে।

এই ভাবে, আমরা সহজেই নতুন প্রকারের আকৃতি যুক্ত করতে কোডের অনুষ্ঠান পরিবর্তন করার প্রয়োজন নেই। এটি বহুরূপতা যেতে কোডে লয়লিতা এবং প্রসারণ আনে।