উত্তর:
আপনি make
যে কাজটি করতে পারবেন তা অন্য কোনও উপায়ে করতে পারবেন না:
এটি ন্যায়সঙ্গত করা একটু কঠিন new
। মূল জিনিসটি এটি সহজ করে তোলে হ'ল নন-কমপোজাইট প্রকারের জন্য পয়েন্টার তৈরি করা। নীচের দুটি ফাংশন সমতুল্য। একটি মাত্র আরও সংক্ষিপ্ত:
func newInt1() *int { return new(int) }
func newInt2() *int {
var i int
return &i
}
m := map[string]int{}
বদলে কী হবে m := make(map[string]int)
? আকার preallocon পাশাপাশি প্রয়োজন নেই।
গো মেমরি বরাদ্দ এবং মান শুরুর একাধিক উপায় রয়েছে:
&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
এটিই তৈরি করা হয়েছে।
make(Point)
এবং make(int)
শেষ 2 লাইনে?
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
new([]int)
, এটি কেবল [] int এর জন্য মেমরি বরাদ্দ করে, তবে আরম্ভ করা হয় না যাতে এটি কেবল ফিরে আসে nil
; মেমোরিটির পয়েন্টার নয় কারণ এটি ব্যবহারযোগ্য নয়। make([]int)
বরাদ্দ এবং সূচনা যাতে এটি ব্যবহারযোগ্য, তারপরে ঠিকানাটি ফিরিয়ে দিন।
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
আপনাকে make()
চ্যানেল এবং মানচিত্র তৈরি করতে হবে (এবং স্লাইসগুলি, তবে সেগুলি অ্যারে থেকেও তৈরি করা যেতে পারে)। এগুলি তৈরি করার কোনও বিকল্প উপায় নেই, সুতরাং আপনি make()
আপনার অভিধান থেকে সরাতে পারবেন না ।
হিসাবে new()
, আমি স্ট্রাক্ট সিনট্যাক্স ব্যবহার করতে পারেন যখন আপনার এটি প্রয়োজন কেন অফহ্যান্ডের কোনও কারণ আমি জানি না । যদিও এর একটি অনন্য অর্থবোধক অর্থ রয়েছে, যা "সমস্ত ক্ষেত্রকে তাদের শূন্য মানের সাথে শুরু করে একটি কাঠামো তৈরি এবং ফিরিয়ে আনুন", যা কার্যকর হতে পারে।
ইফেক্টিভ গোতে বর্ণিত সমস্ত কিছু বাদে new(T)
এবং এর মধ্যে প্রধান পার্থক্যটি &T{}
হ'ল পরেরটি সুস্পষ্টভাবে একটি গাদা বরাদ্দ সম্পাদন করে। তবে এটি লক্ষ করা উচিত যে এটি বাস্তবায়ন নির্ভরতা এবং এইভাবে পরিবর্তিত হতে পারে।
দু'জন সম্পূর্ণ ভিন্ন ফাংশন সম্পাদন করায় তুলনা make
করার new
অর্থ সামান্যই বোধগম্য হয়। তবে লিঙ্কযুক্ত নিবন্ধে এটি বিস্তারিতভাবে ব্যাখ্যা করা হয়েছে।
&T{}
স্পষ্টতভাবে একটি গাদা বরাদ্দ সম্পাদন করে এমন দাবিটি আফাইক, চশমাগুলির কোনও কিছুর উপর ভিত্তি করে নয়। আসলে আমি বিশ্বাস করি এস্কেপ বিশ্লেষণ ইতিমধ্যে যখনই সম্ভব ঠিক তেমন * টি স্ট্যাকের উপর রাখছে new(T)
।
নতুন (টি): এটি টি টাইপ করতে একটি পয়েন্টার ফেরত দেয় * টাইপের মান টি, এটি বরাদ্দ করে এবং মেমরিটিকে শূন্য করে। নতুন (টি) সমতূল্য থেকে & T র {} ।
মেক (টি): এটি টি প্রকারের একটি প্রাথমিক মানের ফেরত দেয় , এটি মেমরির বরাদ্দ করে এবং আরম্ভ করে। এটি টুকরা, মানচিত্র এবং চ্যানেলগুলির জন্য ব্যবহৃত হয়।