আমি কেন ওরফে ফাংশন টাইপ করতে পারি এবং castালাই ছাড়াই সেগুলি ব্যবহার করতে পারি?


98

Go এ, আপনি যদি কোনও নতুন ধরণের সংজ্ঞা দেন তবে:

type MyInt int

তারপরে MyIntআপনি কোনও প্রকারের প্রত্যাশা বা কোনও বিপরীতে কোনও ফাংশনে পাস করতে পারবেন না :

func test(i MyInt) {
    //do something with i
}

func main() {
    anInt := 0
    test(anInt) //doesn't work, int is not of type MyInt
}

ভাল। তবে কেন এটি একই সাথে ফাংশনগুলির ক্ষেত্রে প্রযোজ্য নয়? যেমন:

type MyFunc func(i int)
func (m MyFunc) Run(i int) {
    m(i)
}

func run(f MyFunc, i int) {
    f.Run(i)
}

func main() {
    var newfunc func(int) //explicit declaration
    newfunc = func(i int) {
        fmt.Println(i)
    }
    run(newfunc, 10) //works just fine, even though types seem to differ
}

এখন, আমি অভিযোগ করছি না কারণ এটি আমাকে স্পষ্টভাবে newfuncটাইপ করার জন্য কাস্ট করাতে বাঁচায় MyFunc, যেমন আমাকে প্রথম উদাহরণে করতে হবে; এটি কেবল বেমানান বলে মনে হচ্ছে। আমি নিশ্চিত যে এর কোনও ভাল কারণ আছে; কেউ কি আমাকে আলোকিত করতে পারে?

আমার জিজ্ঞাসার কারণটি হ'ল মূলত কারণ আমি আমার পরিবর্তে দীর্ঘ কিছু ফাংশনের প্রকারগুলি ছোট করতে চাই, তবে আমি এটি নিশ্চিত করতে চাই যে এটি প্রত্যাশিত এবং এটি গ্রহণযোগ্য হবে :)


typeস্কালের চেয়ে গো-তে বরং বেশি কার্যকর। স্কালায় কেবল টাইপ এলিয়াস থাকে, হায়।
রিক -777

4
এখনই আসুন
Hut8

কেউ দ্বিতীয় কোড স্নিপেট ব্যাখ্যা করতে পারে? আমি সত্যিই এই ফাংশনটির ঘোষণা পেতে পারি না
ডেভএক্স

উত্তর:


150

দেখা যাচ্ছে, এটি একটি ভুল বোঝাবুঝি যা গো প্রকারের সাথে কীভাবে আচরণ করা হয়েছিল তা সম্পর্কে, যা অনুমানের সম্পর্কিত অংশটি পড়ে সমাধান করা যেতে পারে:

http://golang.org/ref/spec# টাইপ_পরিচয়

প্রাসঙ্গিক পার্থক্য যে সম্পর্কে আমি অজানা ছিল তা হ'ল নামকরণ এবং নামবিহীন প্রকারের।

নামযুক্ত প্রকারগুলি একটি নামের সাথে টাইপগুলি হয় যেমন ইনট, ইনট .৪, ফ্লোট, স্ট্রিং, বুল। এছাড়াও, 'টাইপ' ব্যবহার করে আপনি যে ধরণের তৈরি করেন তা হ'ল নামযুক্ত প্রকার।

নামবিহীন প্রকারগুলি হ'ল [] স্ট্রিং, ম্যাপ [স্ট্রিং] স্ট্রিং, [4] ইনট। তাদের কোনও নাম নেই, কেবল কীভাবে তারা কাঠামোগত করা যায় তার সাথে সম্পর্কিত একটি বর্ণনা।

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

যেমন নিম্নলিখিত ধরণের দেওয়া:

type MyInt int
type MyMap map[int]int
type MySlice []int
type MyFunc func(int)

নিম্নলিখিতটি অবৈধ:

var i int = 2
var i2 MyInt = 4
i = i2 //both named (int and MyInt) and names don't match, so invalid

নিম্নলিখিতটি ঠিক আছে:

is := make([]int)
m := make(map[int]int)
f := func(i int){}

//OK: comparing named and unnamed type, and underlying representation
//is the same:
func doSlice(input MySlice){...}
doSlice(is)

func doMap(input MyMap){...}
doMap(m)

func doFunc(input MyFunc){...}
doFunc(f)

আমি কিছুটা ক্ষুধা পেয়েছি আমি তাড়াতাড়ি জানতাম না, তাই আমি আশা করি যে অন্য কারও জন্য এই ধরণের লার্কটি স্পষ্ট করে দেয়! এবং এর অর্থ প্রথম ভাবার চেয়ে আমার চেয়ে অনেক কম কাস্টিং :)


4
আপনি এটি ব্যবহার করতে পারেন is := make(MySlice, 0); m := make(MyMap)যা কিছু প্রসঙ্গে আরও পঠনযোগ্য।
বি 2

13

প্রশ্নোত্তর উভয়ই বেশ আলোকিত। তবে, আমি একটি পার্থক্য আনতে চাই যা লাইটনাসের উত্তরে পরিষ্কার নয়।

  • নামযুক্ত প্রকারটি নামবিহীন প্রকারের থেকে পৃথক ।

  • পরিবর্তনশীল নামযুক্ত প্রকার পরিবর্তনশীল করতে হস্তান্তরযোগ্য নয় নামবিহীন প্রকার , তদ্বিপরীত।

  • বিভিন্ন নামযুক্ত প্রকারের পরিবর্তনশীল একে অপরের জন্য নির্ধারিত নয়।

http://play.golang.org/p/uaYHEnofT9

import (
    "fmt"
    "reflect"
)

type T1 []string
type T2 []string

func main() {
    foo0 := []string{}
    foo1 := T1{}
    foo2 := T2{}
    fmt.Println(reflect.TypeOf(foo0))
    fmt.Println(reflect.TypeOf(foo1))
    fmt.Println(reflect.TypeOf(foo2))

    // Output:
    // []string
    // main.T1
    // main.T2

    // foo0 can be assigned to foo1, vice versa
    foo1 = foo0
    foo0 = foo1

    // foo2 cannot be assigned to foo1
    // prog.go:28: cannot use foo2 (type T2) as type T1 in assignment
    // foo1 = foo2
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.