মান রিসিভার বনাম পয়েন্টার রিসিভার


108

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

type T struct {
    a int
}
func (tv  T) Mv(a int) int         { return 0 }  // value receiver
func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver

ডক্স এছাড়াও বলেন, "এই ধরনের মৌলিক ধরনের, টুকরা এবং ক্ষুদ্র structs হিসাবে ধরনের জন্য, একটি মান রিসিভার খুব সস্তা, তাই যদি না পদ্ধতির শব্দার্থবিদ্যা একটি পয়েন্টার প্রয়োজন, একটি মান রিসিভার দক্ষ ও স্পষ্ট।"

প্রথম পয়েন্ট এটি বলে যে এটি "খুব সস্তা", তবে প্রশ্নটি আরও বেশি এটি পয়েন্টার রিসিভারের চেয়ে সস্তা। সুতরাং আমি একটি ছোট বেঞ্চমার্ক তৈরি করেছি (গিস্টের কোড) যা আমাকে দেখিয়েছে যে পয়েন্টার রিসিভার এমন স্ট্রাক্টের জন্য এমনকি দ্রুত যেখানে কেবল একটি স্ট্রিং ফিল্ড রয়েছে। এগুলি ফলাফল:

// Struct one empty string property
BenchmarkChangePointerReceiver  2000000000               0.36 ns/op
BenchmarkChangeItValueReceiver  500000000                3.62 ns/op


// Struct one zero int property
BenchmarkChangePointerReceiver  2000000000               0.36 ns/op
BenchmarkChangeItValueReceiver  2000000000               0.36 ns/op

(সম্পাদনা করুন: দয়া করে নোট করুন যে দ্বিতীয় পয়েন্টটি নতুন গো সংস্করণগুলিতে অবৈধ হয়ে গেছে, মন্তব্য দেখুন)
দ্বিতীয় দফায় এটি বলে যে এটি "দক্ষ এবং পরিষ্কার" যা স্বাদের বিষয়, তাই না? ব্যক্তিগতভাবে আমি সর্বত্র একইভাবে ব্যবহার করে ধারাবাহিকতা পছন্দ করি। দক্ষতা কোন অর্থে? কর্মক্ষমতা অনুযায়ী এটি পয়েন্টার প্রায় সবসময় আরও দক্ষ হয় বলে মনে হয়। একটি সংস্থার সম্পত্তি সহ কয়েকটি পরীক্ষা-নিরীক্ষা মান প্রাপ্তির ন্যূনতম সুবিধা দেখায় (0.01-0.1 এনএস / অপেক্ষার পরিসর)

কেউ কি আমাকে এমন একটি মামলা বলতে পারেন যেখানে কোনও মান রিসিভার স্পষ্টতই আরও বেশি বোঝায় তখন পয়েন্টার রিসিভার? বা আমি মাপদণ্ডে কিছু ভুল করছি, আমি কি অন্যান্য বিষয়গুলি উপেক্ষা করেছি?


3
আমি একটি একক স্ট্রিং ফিল্ড এবং দুটি ক্ষেত্রের সাথে: একই স্ট্রাইক এবং ইন্ট ফিল্ডের সাথে একই ধরণের বেঞ্চমার্ক চালিয়েছি। আমি মান রিসিভারের থেকে দ্রুত ফলাফল পেয়েছি। বেঞ্চমার্ক চ্যাঞ্জপয়েন্টার রিসিভার -4 10000000000 0.99 এনএস / ওপেন বেঞ্চমার্ক চ্যাঞ্জআইটিভ্যালু রিসিভার -4 10000000000 0.33 এনএস / ওপেন এটি 1.8 ব্যবহার করছে। আমি অবাক হয়েছি যে আপনি যখন সর্বশেষে মাপদণ্ডটি চালালেন তখন থেকেই সংকলক অপ্টিমাইজেশানগুলি তৈরি হয়েছিল। আরও বিশদ জন্য সংক্ষেপে দেখুন ।
পিট্টি

2
তুমি ঠিক বলছো. Go1.9 ব্যবহার করে আমার আসল মাপদণ্ডটি চালাচ্ছি, আমি এখনই বিভিন্ন ফলাফল পেয়েছি। পয়েন্টার রিসিভার 0.60 এনএস / অপ, মান রিসিভার 0.38 এনএস / অপ
ক্রিসপোর্ট

উত্তর:


118

নোট করুন যে জিজ্ঞাসিত প্রশ্নাবলী ধারাবাহিকতার উল্লেখ করে

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

এই থ্রেড হিসাবে উল্লিখিত :

গ্রহীতার জন্য পয়েন্টার বনাম মানগুলির নিয়মটি হ'ল মান পদ্ধতিগুলি পয়েন্টার এবং মানগুলিতে আহ্বান করা যায় তবে পয়েন্টার পদ্ধতিগুলি কেবল পয়েন্টারগুলিতেই আহ্বান করা যায়

এখন:

কেউ কি আমাকে এমন একটি মামলা বলতে পারেন যেখানে কোনও মান রিসিভার স্পষ্টতই আরও বেশি বোঝায় তখন পয়েন্টার রিসিভার?

কোড পর্যালোচনা মন্তব্য সাহায্য করতে পারেন:

  • যদি রিসিভারটি কোনও মানচিত্র, ফানক বা চ্যান হয় তবে এটিতে কোনও পয়েন্টার ব্যবহার করবেন না।
  • যদি রিসিভারটি স্লাইস হয় এবং পদ্ধতিটি পুনরায় স্লাইস করে না বা পুনরায় সক্রিয় করে না তবে এটিতে পয়েন্টার ব্যবহার করবেন না।
  • পদ্ধতিটি যদি রিসিভারকে পরিবর্তিত করতে পারে তবে রিসিভারটি অবশ্যই পয়েন্টার হতে হবে।
  • যদি রিসিভার এমন স্ট্রাক্ট থাকে যার মধ্যে একটি sync.Mutexবা অনুরূপ সিঙ্ক্রোনাইজিং ফিল্ড থাকে তবে অনুলিপি এড়ানোর জন্য রিসিভার অবশ্যই পয়েন্টার হতে হবে।
  • যদি রিসিভারটি বড় স্ট্রাক্ট বা অ্যারে হয় তবে পয়েন্টার রিসিভারটি আরও দক্ষ। বড় কত বড়? ধরুন এটি এর সমস্ত উপাদানকে পদ্ধতির আর্গুমেন্ট হিসাবে পাস করার সমতুল্য। যদি এটি খুব বড় মনে হয় তবে এটি প্রাপকের পক্ষে খুব বড়।
  • একযোগে বা এই পদ্ধতি থেকে কল করার সময়, কাজ বা পদ্ধতিগুলি কি রিসিভারকে রূপান্তর করতে পারে? পদ্ধতিটি চালু করা হলে একটি মান প্রকারটি রিসিভারের একটি অনুলিপি তৈরি করে, তাই বাইরের আপডেটগুলি এই রিসিভারের জন্য প্রয়োগ করা হবে না। যদি পরিবর্তনগুলি অবশ্যই মূল রিসিভারে দৃশ্যমান হয় তবে রিসিভারটি অবশ্যই পয়েন্টার হতে হবে।
  • যদি রিসিভারটি স্ট্রাক্ট, অ্যারে বা স্লাইস হয় এবং এর উপাদানগুলির কোনওরূপে এমন কোনও জিনিসের পয়েন্টার হয় যা পরিবর্তিত হতে পারে তবে পয়েন্টার রিসিভারটি পছন্দ করুন, কারণ এটি পাঠকের উদ্দেশ্যে উদ্দেশ্যটি আরও স্পষ্ট করে দেবে।
  • যদি রিসিভারটি একটি ছোট অ্যারে বা কাঠামো যা প্রাকৃতিকভাবে একটি মান ধরণের (উদাহরণস্বরূপ, time.Timeপ্রকারের মতো কিছু ), কোনও পরিবর্তনযোগ্য ক্ষেত্র এবং কোনও পয়েন্টারবিহীন, বা কেবল সাধারণ বা বেস যেমন স্ট্রিংয়ের মতো স্ট্রিং থাকে তবে একটি মান রিসিভার করে ইন্দ্রিয়
    একটি মান গ্রহীতা যে পরিমাণ জঞ্জাল তৈরি করতে পারে তা হ্রাস করতে পারে; যদি মানটি কোনও মান পদ্ধতির কাছে চলে যায় তবে গাদাতে বরাদ্দ না দিয়ে একটি অন-স্ট্যাক অনুলিপি ব্যবহার করা যেতে পারে। (সংকলক এই বরাদ্দ এড়ানো সম্পর্কে স্মার্ট হওয়ার চেষ্টা করে তবে এটি সর্বদা সফল হতে পারে না)) প্রথমে প্রোফাইল না দিয়ে এই কারণে কোনও মান রিসিভার টাইপ চয়ন করবেন না।
  • অবশেষে, সন্দেহ হলে, পয়েন্টার রিসিভার ব্যবহার করুন।

গা bold় অংশটি উদাহরণস্বরূপ পাওয়া যায় net/http/server.go#Write():

// Write writes the headers described in h to w.
//
// This method has a value receiver, despite the somewhat large size
// of h, because it prevents an allocation. The escape analysis isn't
// smart enough to realize this function doesn't mutate h.
func (h extraHeader) Write(w *bufio.Writer) {
...
}

16
The rule about pointers vs. values for receivers is that value methods can be invoked on pointers and values, but pointer methods can only be invoked on pointers আসলে সত্য নয়। উভয়ই মান রিসিভার এবং পয়েন্টার রিসিভার পদ্ধতি সঠিকভাবে টাইপ করা পয়েন্টার বা নন-পয়েন্টারটিতে আহ্বান করা যেতে পারে। পদ্ধতিটি যাকে বলা হয় তা নির্বিশেষে, পদ্ধতির শরীরে রিসিভারের শনাক্তকারী একটি মান রিসিভার ব্যবহার করার সময় বাই-কপি মান এবং পয়েন্টার রিসিভার ব্যবহার করার সময় একটি পয়েন্টার নির্দেশ করে
হার্ট

3
এখানে একটি দুর্দান্ত ব্যাখ্যা রয়েছে "যদি এক্স ঠিকানাযুক্ত হয় এবং & এক্স এর পদ্ধতিতে এম থাকে, তবে xm () (& x) .m () এর জন্য সংক্ষিপ্ত হয়" "
তেরা

@tera হ্যাঁ: এ আলোচনা করা হয় যে stackoverflow.com/q/43953187/6309
VonC

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

@ হার্টসিংহ আমার মনে হয় উপরের পোস্টটি সত্যটি নির্দেশ করছে যে পয়েন্টার রিসিভার পদ্ধতিগুলি মান ধরণের জন্য "পদ্ধতি সেট" তে নেই। আপনার সংযুক্ত খেলার মাঠ, নিম্নলিখিত লাইন যোগ সংকলন ত্রুটি স্থাপিত হবে: Int(5).increment_by_one_ptr()। একইভাবে, পদ্ধতিটি নির্ধারণ করে এমন একটি বৈশিষ্ট্য increment_by_one_ptrধরণের মান দিয়ে সন্তুষ্ট হবে না Int
গৌরব আগরওয়াল

16

অতিরিক্তভাবে যোগ করার জন্য @ ভনসি দুর্দান্ত, তথ্যমূলক উত্তর।

আমি অবাক হয়েছি যে কেউ একবার প্রকল্পটি বড় হয়ে গেলে, পুরানো ডেভস ছেড়ে চলে আসে এবং নতুন আসে তখন রক্ষণাবেক্ষণ ব্যয়ের সত্যই উল্লেখ করেনি। গো অবশ্যই একটি তরুণ ভাষা।

সাধারণভাবে বলতে গেলে, আমি যখন পারি তখন পয়েন্টারগুলি এড়াতে চেষ্টা করি তবে তাদের জায়গা এবং সৌন্দর্য আছে।

আমি পয়েন্টার ব্যবহার করি যখন:

  • বড় ডেটাসেটের সাথে কাজ করা
  • স্ট্রাক্ট রক্ষণাবেক্ষণের একটি স্টেট রয়েছে, যেমন টোকেনক্যাচ,
    • আমি নিশ্চিত করি যে সমস্ত ক্ষেত্রগুলি বেসরকারী, কেবল সংজ্ঞায়িত পদ্ধতি রিসিভারের মাধ্যমে মিথস্ক্রিয়া সম্ভব
    • আমি এই ফাংশনটি কোনও গুরোটিনের কাছে পৌঁছে দিই না

উদাহরণ:

type TokenCache struct {
    cache map[string]map[string]bool
}

func (c *TokenCache) Add(contract string, token string, authorized bool) {
    tokens := c.cache[contract]
    if tokens == nil {
        tokens = make(map[string]bool)
    }

    tokens[token] = authorized
    c.cache[contract] = tokens
}

আমি পয়েন্টারগুলি এড়িয়ে যাওয়ার কারণগুলি:

  • পয়েন্টারগুলি একই সাথে নিরাপদ নয় (গো ল্যাং এর পুরো পয়েন্ট)
  • একবার পয়েন্টার রিসিভার, সর্বদা পয়েন্টার রিসিভার (ধারাবাহিকতার জন্য সমস্ত স্ট্রাক্টের পদ্ধতিগুলির জন্য)
  • "মূল্য অনুলিপি ব্যয়ের সাথে" তুলনা বজায় রাখা মিটেক্সগুলি অবশ্যই আরও ব্যয়বহুল, ধীর এবং শক্ত
  • "মান কপি ব্যয়" কথা বলছি, আসলেই কি এটি একটি সমস্যা? অকালীন অপটিমাইজেশন সমস্ত অশুভের মূল, আপনি সর্বদা পরে পয়েন্টার যুক্ত করতে পারেন
  • এটি সরাসরি, ইচ্ছাকৃতভাবে আমাকে ছোট স্ট্রাক্টগুলি ডিজাইন করতে বাধ্য করে
  • সুস্পষ্ট উদ্দেশ্য এবং সুস্পষ্ট আই / ও দিয়ে খাঁটি ফাংশনগুলি ডিজাইন করে পয়েন্টারগুলি বেশিরভাগ এড়ানো যায়
  • আমি বিশ্বাস করি এমন পয়েন্টারগুলির সাথে আবর্জনা সংগ্রহ করা আরও শক্ত
  • এনক্যাপসুলেশন, দায়িত্ব সম্পর্কে তর্ক করা সহজ
  • এটিকে সরল রাখুন, নির্বোধ (হ্যাঁ, পয়েন্টারগুলি জটিল হতে পারে কারণ আপনি পরবর্তী প্রকল্পের দেব কখনই জানেন না)
  • ইউনিট টেস্টিং গোলাপী উদ্যানের মধ্য দিয়ে হাঁটার মতো (একমাত্র প্রকাশ বাকী বাক্স), এর অর্থ সহজ
  • শর্ত নেই (এনআইএল পাস করা যেতে পারে যেখানে পয়েন্টার আশা করা হত)

আমার থাম্বের নিয়ম, যতটা সম্ভব এনপ্যাপুলেটেড পদ্ধতি যেমন লিখুন:

package rsa

// EncryptPKCS1v15 encrypts the given message with RSA and the padding scheme from PKCS#1 v1.5.
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
    return []byte("secret text"), nil
}

cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) 

হালনাগাদ:

এই প্রশ্নের আরো বিষয় খোঁজ খবর নেন এবং এটি সম্পর্কে একটি ব্লগ পোস্ট লিখতে আমাকে অনুপ্রাণিত https://medium.com/gophersland/gopher-vs-object-oriented-golang-4fa62b88c701


আপনি এখানে যা বলছেন তার 99% পছন্দ করি এবং এর সাথে দৃ strongly়ভাবে সম্মত হন। এটি বলেছিল আমি ভাবছি যে আপনার উদাহরণটি আপনার পয়েন্টটি বোঝানোর সর্বোত্তম উপায়। টোকেনকেই মূলত কোনও মানচিত্র নয় (@ ভনসি থেকে - "যদি রিসিভারটি মানচিত্র, ফানক বা চ্যান হয় তবে এটিতে কোনও পয়েন্টার ব্যবহার করবেন না")। মানচিত্রগুলি যেহেতু রেফারেন্সের ধরণ তাই "যুক্ত ()" পয়েন্টার রিসিভার তৈরি করে আপনি কী অর্জন করবেন? টোকেনকেশের যে কোনও অনুলিপি একই মানচিত্রের উল্লেখ করবে। এই গো খেলার মাঠটি দেখুন - play.golang.com/p/Xda1rsGwvhq
সমৃদ্ধ

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

এলএল, আবার অনুলিপি / পেস্ট! 😉 আইএমও আপনি এটিকে ছেড়ে যেতে পারেন যেহেতু এটি একটি ফাঁদ যা সহজেই পড়ে যায় তার চিত্র দেয় বা আপনি মানচিত্রটিকে এমন কিছু (গুলি) দিয়ে প্রতিস্থাপন করতে পারেন যা রাষ্ট্র এবং / অথবা একটি বৃহত ডেটা কাঠামো প্রদর্শন করে।
ধনী

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