আমি কেন () বা নতুন () তৈরি করব?


203

ভূমিকা নথিগুলি new()এবং এর মধ্যে পার্থক্য ব্যাখ্যা করার জন্য অনেক অনুচ্ছেদকে উত্সর্গ করে তবে বাস্তবে make()আপনি স্থানীয় ক্ষেত্রের মধ্যে অবজেক্ট তৈরি করতে এবং সেগুলি ফিরিয়ে দিতে পারেন।

কেন আপনি বরাদ্দকারীদের জোড়া ব্যবহার করবেন?

উত্তর:


170

আপনি makeযে কাজটি করতে পারবেন তা অন্য কোনও উপায়ে করতে পারবেন না:

  • একটি চ্যানেল তৈরি করুন
  • পূর্বনির্ধারিত স্থান সহ একটি মানচিত্র তৈরি করুন
  • পূর্বনির্ধারিত স্থান বা লেন! = ক্যাপ সহ একটি স্লাইস তৈরি করুন

এটি ন্যায়সঙ্গত করা একটু কঠিন new। মূল জিনিসটি এটি সহজ করে তোলে হ'ল নন-কমপোজাইট প্রকারের জন্য পয়েন্টার তৈরি করা। নীচের দুটি ফাংশন সমতুল্য। একটি মাত্র আরও সংক্ষিপ্ত:

func newInt1() *int { return new(int) }

func newInt2() *int {
    var i int
    return &i
}

41
এটি সত্য যে চ্যানেল তৈরি করতে 'নতুন' ব্যবহার করা যায় না। তবে, আমার মতে, বক্তব্যটি হ'ল: 'নতুন' এবং 'মেক' কোনও একক অন্তর্নির্মিত কার্যক্রমে যোগদান করলে কী হবে? অবশ্যই, এই ধরনের প্রতিস্থাপন সম্ভব হবে। যেহেতু এটি সম্ভব, প্রশ্নটি হল: কেবলমাত্র 1 টি বিল্ট-ইন ফাংশনটির চেয়ে 2 বিল্ট-ইন ফাংশনগুলি করার উদ্দেশ্যগত কারণগুলি কী। - আপনার উত্তরটি সঠিকভাবে বলেছে যে 'নতুন' চ্যানেল / মানচিত্র / স্লাইস তৈরি করতে ব্যবহার করা যাবে না, তবে এটি কেন 1 টি সাধারণ বরাদ্দ + আরআর ক্রিয়াকলাপের পরিবর্তে গো 'নতুন' এবং 'মেক' করেছে তার কোন যুক্তি সরবরাহ করে না ।

5
এগুলি একত্রিত করা যেতে পারে এবং এটি রব পাইক দ্বারা এমনকি এক পর্যায়ে প্রস্তাব করা হয়েছিল: groups.google.com/d/topic/golang-nuts/kWXYU95XN04/ddusussion । শেষ পর্যন্ত এটি আপনার উত্তরের সাথে সদৃশ কারণগুলির মধ্যে দিয়ে যায় নি।
ইভান শ

12
কার্যকর গো পয়েন্টটি দেয় যে নতুনটি একটি শূন্য মান দেয়, যেখানে মানচিত্র অ-শূন্যস্থানযুক্ত মানচিত্র, স্লাইস বা চ্যানেল বরাদ্দ করে। দেখুন golang.org/doc/effective_go.html#allocation_new
kristianp

এর m := map[string]int{}বদলে কী হবে m := make(map[string]int)? আকার preallocon পাশাপাশি প্রয়োজন নেই।
নোয়াম মানস

165

গো মেমরি বরাদ্দ এবং মান শুরুর একাধিক উপায় রয়েছে:

&T{...}, &someLocalVar, new,make

যৌগিক আক্ষরিক তৈরি করার সময় বরাদ্দও ঘটতে পারে।


newপূর্ণসংখ্যার মতো মান বরাদ্দ করতে ব্যবহার করা যেতে পারে &intএটি অবৈধ:

new(Point)
&Point{}      // OK
&Point{2, 3}  // Combines allocation and initialization

new(int)
&int          // Illegal

// Works, but it is less convenient to write than new(int)
var i int
&i

মধ্যে পার্থক্য newএবং makeনিম্নলিখিত উদাহরণে দিকে তাকিয়ে দেখা যেতে পারে:

p := new(chan int)   // p has type: *chan int
c := make(chan int)  // c has type: chan int

ধরুন গো এর নেই newএবং makeতবে এতে বিল্ট-ইন ফাংশন রয়েছে NEW। তারপরে উদাহরণ কোডটি দেখতে এই রকম হবে:

p := NEW(*chan int)  // * is mandatory
c := NEW(chan int)

* বাধ্যতামূলক হবে , তাই:

new(int)        -->  NEW(*int)
new(Point)      -->  NEW(*Point)
new(chan int)   -->  NEW(*chan int)
make([]int, 10) -->  NEW([]int, 10)

new(Point)  // Illegal
new(int)    // Illegal

হ্যাঁ, মার্জ করা newএবং makeএকটি একক অন্তর্নির্মিত ফাংশনে যুক্ত করা সম্ভব। তবে এটি সম্ভবত সম্ভাব্য যে কোনও একটি অন্তর্নির্মিত ফাংশন দুটি বিল-ইন ফাংশন না করে নতুন গো প্রোগ্রামারদের মধ্যে আরও বিভ্রান্তির কারণ ঘটায়।

উপরের সমস্ত বিষয় বিবেচনা করে, এটি পৃথক থাকার পক্ষে newএবং আরও উপযুক্ত বলে মনে makeহয়।


@ টর্স্টেনব্রোনার আমি পড়তে আরও সহজ হতে পেলাম এবং দেখান যে intএটিই তৈরি করা হয়েছে।
ড্যানিয়েল তোয়েব

4
আপনি কি লিখতে চেয়েছিলেন make(Point)এবং make(int)শেষ 2 লাইনে?
জিমি হুচ

27

makeফাংশন কেবল স্লাইস, মানচিত্র, বা চ্যান টাইপের কোনও অবজেক্ট বরাদ্দ করে এবং আরম্ভ করে। মত new, প্রথম যুক্তি একটি প্রকার। তবে এটি একটি দ্বিতীয় যুক্তি, আকারও নিতে পারে। নতুনের মতো নয়, মেকের রিটার্ন টাইপ তার যুক্তির প্রকারের মতো, এটির কোনও পয়েন্টার নয়। এবং বরাদ্দকৃত মানটি আরম্ভ করা হয় (নতুনের মতো শূন্যমূল্যে সেট করা নেই)। কারণটি হ'ল স্লাইস, মানচিত্র এবং চ্যান হ'ল ডেটা স্ট্রাকচার। তাদের সূচনা করা দরকার, অন্যথায় তারা ব্যবহারযোগ্য হবে না। এই কারণেই নতুন () এবং মেক () আলাদা হওয়া দরকার।

ইফেক্টিভ গো থেকে নিম্নলিখিত উদাহরণগুলি এটি খুব স্পষ্ট করে তুলেছে:

p *[]int = new([]int) // *p = nil, which makes p useless
v []int = make([]int, 100) // creates v structure that has pointer to an array, length field, and capacity field. So, v is immediately usable

1
ইন new([]int), এটি কেবল [] int এর জন্য মেমরি বরাদ্দ করে, তবে আরম্ভ করা হয় না যাতে এটি কেবল ফিরে আসে nil; মেমোরিটির পয়েন্টার নয় কারণ এটি ব্যবহারযোগ্য নয়। make([]int)বরাদ্দ এবং সূচনা যাতে এটি ব্যবহারযোগ্য, তারপরে ঠিকানাটি ফিরিয়ে দিন।
o0omycomputero0o

12
  • new(T)- বরাদ্দ মেমরি, এবং এটি সেট শূন্য মান টাইপ জন্য টি ..
    ..that হয় 0জন্য int- এ , ""জন্য স্ট্রিং এবং nilরেফারেন্সড প্রকার (জন্য ফালি , মানচিত্র , চ্যান )

    দ্রষ্টব্য যে রেফারেন্সযুক্ত প্রকারগুলি কেবলমাত্র কিছু অন্তর্নিহিত ডেটা স্ট্রাকচারের জন্য পয়েন্টার , যা উদাহরণ দ্বারা তৈরি করা হবে নাnew(T)
    : স্লাইসের ক্ষেত্রে , অন্তর্নিহিত অ্যারে তৈরি করা হবে না, সুতরাং new([]int) কিছুইকে একটি পয়েন্টার ফেরত দেয়

  • make(T)- রেফারেন্স করা ডেটা ধরণের ( স্লাইস , ম্যাপ , চ্যান ) জন্য মেমরি বরাদ্দ করে , এবং তাদের অন্তর্নিহিত ডেটা স্ট্রাকচারকে আরম্ভ করে

    উদাহরণ: স্লাইসের ক্ষেত্রে , অন্তর্নিহিত অ্যারে নির্দিষ্ট দৈর্ঘ্য এবং ক্ষমতা সহ তৈরি করা হবে
    মনে রাখবেন যে সি এর তুলনায় একটি অ্যারে গোতে একটি প্রাথমিক ধরণ!


বলা হচ্ছে যে:

  • make(T) সম্মিলিত-আক্ষরিক সিনট্যাক্সের মতো আচরণ করে
  • new(T)এর মতো আচরণ করে var(যখন ভেরিয়েবলটি আরম্ভ হয় না)

    func main() {
        fmt.Println("-- MAKE --")
        a := make([]int, 0)
        aPtr := &a
        fmt.Println("pointer == nil :", *aPtr == nil)
        fmt.Printf("pointer value: %p\n\n", *aPtr)
    
        fmt.Println("-- COMPOSITE LITERAL --")
        b := []int{}
        bPtr := &b
        fmt.Println("pointer == nil :", *bPtr == nil)
        fmt.Printf("pointer value: %p\n\n", *bPtr)
    
        fmt.Println("-- NEW --")
        cPtr := new([]int)
        fmt.Println("pointer == nil :", *cPtr == nil)
        fmt.Printf("pointer value: %p\n\n", *cPtr)
    
        fmt.Println("-- VAR (not initialized) --")
        var d []int
        dPtr := &d
        fmt.Println("pointer == nil :", *dPtr == nil)
        fmt.Printf("pointer value: %p\n", *dPtr)
    }

    প্রোগ্রাম চালান

    -- MAKE --
    pointer == nil : false
    pointer value: 0x118eff0  # address to underlying array
    
    -- COMPOSITE LITERAL --
    pointer == nil : false
    pointer value: 0x118eff0  # address to underlying array
    
    -- NEW --
    pointer == nil : true
    pointer value: 0x0
    
    -- VAR (not initialized) --
    pointer == nil : true
    pointer value: 0x0

    আরও পড়া:
    https://golang.org/doc/effective_go.html#allocation_new https://golang.org/doc/effective_go.html#allocation_make


  • জিনিস একটি উদাহরণ দিয়ে আরও স্পষ্ট হয়ে ওঠে। upvated :)
    সুমিত ঝা

    8

    আপনাকে make()চ্যানেল এবং মানচিত্র তৈরি করতে হবে (এবং স্লাইসগুলি, তবে সেগুলি অ্যারে থেকেও তৈরি করা যেতে পারে)। এগুলি তৈরি করার কোনও বিকল্প উপায় নেই, সুতরাং আপনি make()আপনার অভিধান থেকে সরাতে পারবেন না ।

    হিসাবে new(), আমি স্ট্রাক্ট সিনট্যাক্স ব্যবহার করতে পারেন যখন আপনার এটি প্রয়োজন কেন অফহ্যান্ডের কোনও কারণ আমি জানি না । যদিও এর একটি অনন্য অর্থবোধক অর্থ রয়েছে, যা "সমস্ত ক্ষেত্রকে তাদের শূন্য মানের সাথে শুরু করে একটি কাঠামো তৈরি এবং ফিরিয়ে আনুন", যা কার্যকর হতে পারে।


    1
    সুতরাং নতুন এড়ানো উচিত এবং কেবল স্ট্রাক্ট সিনট্যাক্সের ব্যবহার পছন্দ করুন
    কমনসেন্সকোড ২

    8

    ইফেক্টিভ গোতে বর্ণিত সমস্ত কিছু বাদে new(T)এবং এর মধ্যে প্রধান পার্থক্যটি &T{}হ'ল পরেরটি সুস্পষ্টভাবে একটি গাদা বরাদ্দ সম্পাদন করে। তবে এটি লক্ষ করা উচিত যে এটি বাস্তবায়ন নির্ভরতা এবং এইভাবে পরিবর্তিত হতে পারে।

    দু'জন সম্পূর্ণ ভিন্ন ফাংশন সম্পাদন করায় তুলনা makeকরার newঅর্থ সামান্যই বোধগম্য হয়। তবে লিঙ্কযুক্ত নিবন্ধে এটি বিস্তারিতভাবে ব্যাখ্যা করা হয়েছে।


    10
    &T{}স্পষ্টতভাবে একটি গাদা বরাদ্দ সম্পাদন করে এমন দাবিটি আফাইক, চশমাগুলির কোনও কিছুর উপর ভিত্তি করে নয়। আসলে আমি বিশ্বাস করি এস্কেপ বিশ্লেষণ ইতিমধ্যে যখনই সম্ভব ঠিক তেমন * টি স্ট্যাকের উপর রাখছে new(T)
    zzzz

    6

    নতুন (টি): এটি টি টাইপ করতে একটি পয়েন্টার ফেরত দেয় * টাইপের মান টি, এটি বরাদ্দ করে এবং মেমরিটিকে শূন্য করে। নতুন (টি) সমতূল্য থেকে & T র {}

    মেক (টি): এটি টি প্রকারের একটি প্রাথমিক মানের ফেরত দেয় , এটি মেমরির বরাদ্দ করে এবং আরম্ভ করে। এটি টুকরা, মানচিত্র এবং চ্যানেলগুলির জন্য ব্যবহৃত হয়।

    আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
    Licensed under cc by-sa 3.0 with attribution required.