গো Oচ্ছিক পরামিতি?


464

যেতে কি optionচ্ছিক পরামিতি থাকতে পারে? অথবা আমি একই নাম এবং বিভিন্ন সংখ্যক যুক্তি দিয়ে দুটি ফাংশন সংজ্ঞায়িত করতে পারি?


সম্পর্কিত: বৈকল্পিক theচ্ছিক পরামিতি হিসাবে ব্যবহার করার সময় বাধ্যতামূলক পরামিতিগুলি প্রয়োগ করার জন্য এটি কীভাবে করা যায়: গোলাংয়ে কাস্টম লাইব্রেরি সহ সংকলন সময়ের ত্রুটিটি ট্রিগার করা সম্ভব?
আইকজা

11
গুগল একটি ভয়াবহ সিদ্ধান্ত নিয়েছে, কারণ কখনও কখনও কোনও ফাংশনে 90% ব্যবহারের ক্ষেত্রে এবং তারপরে 10% ব্যবহারের কেস থাকে। Alচ্ছিক যুক্তিটি 10% ব্যবহারের ক্ষেত্রে। স্যান ডিফল্ট মানে কম কোড, কম কোড মানে বেশি রক্ষণাবেক্ষণ।
জোনাথন

উত্তর:


431

গোয়ের alচ্ছিক পরামিতি নেই বা এটি পদ্ধতি ওভারলোডিং সমর্থন করে না :

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


58
কি makeএকটি বিশেষ ক্ষেত্রে তারপর? বা এটি কি সত্যই কোনও কার্য হিসাবে প্রয়োগ করা হয়নি ...
এম

65
@ এমকে 12 makeএকটি ভাষা নির্মাণ এবং উপরে বর্ণিত বিধিগুলি প্রয়োগ হয় না। দেখুন এই সংশ্লিষ্ট প্রশ্ন
নিমো

7
rangeএকই কেস হিসাবে make, যে অর্থে
thiagowfx

14
পদ্ধতি ওভারলোডস - তত্ত্বের একটি দুর্দান্ত ধারণা এবং যখন ভাল প্রয়োগ করা হয় তখন দুর্দান্ত। তবে আমি বাস্তবে আবর্জনা অনিবার্য ওভারলোডিং প্রত্যক্ষ করেছি এবং তাই গুগলের সিদ্ধান্তের সাথে একমত
হব

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

216

Paraচ্ছিক প্যারামিটারগুলির মতো কিছু অর্জনের একটি দুর্দান্ত উপায় হ'ল ভেরিয়াদিক আরোগুলি ব্যবহার করা। ফাংশনটি আসলে আপনি যা নির্দিষ্ট বলুন তার স্লাইস পাবেন receives

func foo(params ...int) {
    fmt.Println(len(params))
}

func main() {
    foo()
    foo(1)
    foo(1,2,3)
}

"ফাংশনটি আসলে আপনি যে ধরণের নির্দিষ্ট করেন তার একটি স্লাইস পাবেন" কীভাবে?
অ্যালিক্স এক্সেল

3
উপরের উদাহরণে, params
অন্তর্নির্মিত

76
তবে কেবল একই ধরণের প্যারামের জন্য :(
জুয়ান ডি পরাস

15
@ জুয়ান্ডপ্যারাস ভাল, আপনি এখনও ... ইন্টারফেসের মতো কিছু ব্যবহার করতে পারেন} gu আমার ধারণা।
মাওফেল

5
... টাইপ সহ আপনি স্বতন্ত্র বিকল্পগুলির অর্থ বোঝাচ্ছেন না। পরিবর্তে একটি কাঠামো ব্যবহার করুন। ... টাইপ মানগুলির জন্য কার্যকর যা আপনার অন্যথায় কল করার আগে একটি অ্যারে রাখতে হবে।
ব্যবহারকারী 3523091

169

আপনি এমন একটি কাঠামো ব্যবহার করতে পারেন যার মধ্যে পরামিতিগুলি রয়েছে:

type Params struct {
  a, b, c int
}

func doIt(p Params) int {
  return p.a + p.b + p.c 
}

// you can call it without specifying all parameters
doIt(Params{a: 1, c: 9})

12
স্ট্রাইকগুলির ডিফল্ট মান থাকতে পারে তবে এটি দুর্দান্ত হবে; ব্যবহারকারী বাদ দেওয়া যে কোনও কিছুই সেই ধরণের নীল মানের জন্য খেলাপি হয়, যা ফাংশনে উপযুক্ত ডিফল্ট যুক্তি হতে পারে বা নাও হতে পারে।
jsdw

41
@ এলিটনাস, কেশ বিভক্ত করতে আমি ঘৃণা করি, তবে যে ক্ষেত্রগুলির জন্য মানগুলি বাদ দেওয়া হয় সেগুলি তাদের ধরণের জন্য 'শূন্য মান' -এ ডিফল্ট হবে; শিল একটি ভিন্ন প্রাণী। বাদ দেওয়া ক্ষেত্রের ধরণটি যদি একটি পয়েন্টার হতে থাকে তবে শূন্যের মান শূন্য হবে।
বুধবার

2
@ বারফ্ল হ্যাঁ, "শূন্য মান" এর ধারণা ব্যতীত ইন / ফ্লোট / স্ট্রিং প্রকারের জন্য একেবারেই অকেজো, কারণ এই মানগুলি অর্থবহ এবং সুতরাং যদি মানটি কাঠামো থেকে বাদ দেওয়া হয় বা শূন্য মান হয় তবে আপনি পার্থক্যটি বলতে পারবেন না ইচ্ছাকৃতভাবে পাস।
কীমোন

3
@ কীমন, আমি আপনার সাথে একমত নই আমি কেবল উপরের বিবৃতিটি সম্পর্কে প্যাডেন্টিক ছিলাম যে ব্যবহারকারীরা ডিফল্ট দ্বারা বাদ দেওয়া মানগুলি "সেই ধরণের নীল মান" থেকে বাদ দেয়, যা ভুল। এগুলি শূন্য মানতে ডিফল্ট হয়, যা টাইপটি পয়েন্টার কিনা তার উপর নির্ভর করে শূন্য হতে পারে বা নাও হতে পারে।
বুধবার

123

অবাধ, ঐচ্ছিক প্যারামিটার সম্ভাব্য সংখ্যক, একটি চমৎকার বাগ্ধারা ব্যবহার করা ক্রিয়াগত অপশন

আপনার ধরণের জন্য Foobar, প্রথমে কেবলমাত্র একজন নির্মাতা লিখুন:

func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){
  fb := &Foobar{}
  // ... (write initializations with default values)...
  for _, op := range options{
    err := op(fb)
    if err != nil {
      return nil, err
    }
  }
  return fb, nil
}

যেখানে প্রতিটি বিকল্প একটি ফাংশন যা ফুবারকে পরিবর্তন করে। তারপরে আপনার ব্যবহারকারীর মানক বিকল্পগুলি ব্যবহার বা তৈরি করার জন্য সুবিধাজনক উপায় সরবরাহ করুন, উদাহরণস্বরূপ:

func OptionReadonlyFlag(fb *Foobar) error {
  fb.mutable = false
  return nil
}

func OptionTemperature(t Celsius) func(*Foobar) error {
  return func(fb *Foobar) error {
    fb.temperature = t
    return nil
  }
}

খেলার মাঠ

সংক্ষিপ্ততার জন্য, আপনি বিকল্পগুলির ( খেলার মাঠ ) ধরণের নাম দিতে পারেন :

type OptionFoobar func(*Foobar) error

আপনার যদি বাধ্যতামূলক প্যারামিটারগুলির প্রয়োজন হয় তবে এগুলি বৈচিত্রের আগে নির্মাণকারীর প্রথম যুক্তি হিসাবে যুক্ত করুন options

কার্যকরী বিকল্পগুলির মূল উপকারগুলি হ'ল:

  • আপনার এপিআই বিদ্যমান কোডটি ভঙ্গ না করে সময়ের সাথে বাড়তে পারে কারণ নতুন বিকল্পগুলির প্রয়োজন হলে কনডাক্টর স্বাক্ষর একই থাকে।
  • এটি ডিফল্ট ব্যবহারের কেসটিকে এর সহজতম হিসাবে সক্ষম করে: কোনও যুক্তিই নেই!
  • এটি জটিল মানগুলির সূচনার উপর সূক্ষ্ম নিয়ন্ত্রণ সরবরাহ করে।

এই কৌশলটি রব পাইক দ্বারা তৈরি করা হয়েছিল এবং ডেভ চেনিও প্রদর্শন করেছিলেন ।



15
চতুর, তবে খুব জটিল। গো দর্শন হল সোজা পদ্ধতিতে কোড লেখা। কেবল একটি কাঠামো পাস করুন এবং ডিফল্ট মানগুলির জন্য পরীক্ষা করুন।
ব্যবহারকারী 3523091

9
কমপক্ষে প্রথম প্রকাশক হিসাবে উল্লেখ করা এই মূর্খতার মূল লেখক কেবল এফওয়াইআই হলেন কমান্ডার রব পাইক, যাকে আমি গো দর্শনের পক্ষে যথেষ্ট অনুমোদিত মনে করি। লিঙ্ক - কমান্ডসেন্টার.ব্লগস্পট.বিজি / 2014 / 01/… । এছাড়াও "সরল জটিল" অনুসন্ধান করুন।
পেটার ডনচেভ

2
# জেএমটিসিডব্লিউ, তবে আমি এই পদ্ধতির বিষয়ে যুক্তিযুক্ত হওয়া খুব কঠিন বলে মনে করি। আমি এখন পর্যন্ত মূল্যবোধের কাঠামোয় পাস করতে পছন্দ করব, যার বৈশিষ্ট্যগুলি func()যদি প্রয়োজন হয় তবে এটি প্রয়োজনের চেয়ে আমার মস্তিষ্ককে বাঁকিয়ে দেয়। যখনই আমাকে এই পদ্ধতির ব্যবহার করতে হবে, যেমন ইকো লাইব্রেরির সাথে, আমি দেখতে পাই আমার মস্তিষ্ক বিমূর্ততার খরগোশের গর্তে আটকা পড়েছে। #fww
মাইকচিন্কেল

ধন্যবাদ, এই প্রতিমাটির সন্ধান করছিলাম। গ্রহণযোগ্য উত্তর হিসাবে পাশাপাশি থাকতে পারে।
r --------- কে


6

না - না। সি ++ প্রোগ্রামার ডক্সের জন্য গো প্রতি

গো ফাংশন ওভারলোডিং সমর্থন করে না এবং ব্যবহারকারী সংজ্ঞায়িত অপারেটরদের সমর্থন করে না।

Anচ্ছিক পরামিতিগুলি অসমর্থিত, তবে সেগুলিও সমর্থিত নয় equally


8
"এই [alচ্ছিক পরামিতি ]গুলির জন্য কোনও বর্তমান পরিকল্পনা নেই।" ইয়ান ল্যান্স টেইলর, গো ভাষার দল। groups.google.com/group/golang-nuts/msg/030e63e7e681fd3e
পিটারএসও

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

4

আপনি নীচের মত অনুরূপ একটি চমত্কার এ বেশ সুন্দরভাবে encapsulate করতে পারেন।

package main

import (
        "bufio"
        "fmt"
        "os"
)

func main() {
        fmt.Println(prompt())
}

func prompt(params ...string) string {
        prompt := ": "
        if len(params) > 0 {
                prompt = params[0]
        }
        reader := bufio.NewReader(os.Stdin)
        fmt.Print(prompt)
        text, _ := reader.ReadString('\n')
        return text
}

এই উদাহরণে, পূর্বনির্ধারিতভাবে প্রম্পটের একটি কোলন এবং এর সামনে একটি স্থান থাকে। । ।

: 

। । । তবে আপনি প্রম্পট ফাংশনে একটি প্যারামিটার সরবরাহ করে সেটি ওভাররাইড করতে পারেন।

prompt("Input here -> ")

এটি নীচের মত একটি অনুরোধে ফলাফল হবে।

Input here ->

3

আমি প্যারাম এবং ভেরিয়াদিক আরোগুলির কাঠামোর সংমিশ্রণটি ব্যবহার করে শেষ করেছি। এইভাবে, আমাকে বিদ্যমান ইন্টারফেসটি পরিবর্তন করতে হয়নি যা বেশ কয়েকটি পরিষেবা দ্বারা গ্রাস করা হয়েছিল এবং আমার পরিষেবাটি প্রয়োজনীয় হিসাবে অতিরিক্ত প্যারামগুলি পাস করতে সক্ষম হয়েছিল। গোলাং খেলার মাঠে নমুনা কোড: https://play.golang.org/p/G668FA97Nu


3

গো ল্যাঙ্গুয়েজ পদ্ধতি ওভারলোডিং সমর্থন করে না, তবে আপনি বৈকল্পিক আরোগুলি যেমন justচ্ছিক পরামিতিগুলির মতো ব্যবহার করতে পারেন, আপনি ইন্টারফেস interface para পরামিতি হিসাবেও ব্যবহার করতে পারেন তবে এটি কোনও পছন্দ নয় a


2

আমি কিছুটা দেরি করেছি, তবে আপনি যদি সাবলীল ইন্টারফেস পছন্দ করেন তবে আপনি সম্ভবত এইভাবে শিকলযুক্ত কলগুলির জন্য আপনার সেটারগুলি ডিজাইন করতে পারেন:

type myType struct {
  s string
  a, b int
}

func New(s string, err *error) *myType {
  if s == "" {
    *err = errors.New(
      "Mandatory argument `s` must not be empty!")
  }
  return &myType{s: s}
}

func (this *myType) setA (a int, err *error) *myType {
  if *err == nil {
    if a == 42 {
      *err = errors.New("42 is not the answer!")
    } else {
      this.a = a
    }
  }
  return this
}

func (this *myType) setB (b int, _ *error) *myType {
  this.b = b
  return this
}

এবং তারপরে এটিকে কল করুন:

func main() {
  var err error = nil
  instance :=
    New("hello", &err).
    setA(1, &err).
    setB(2, &err)

  if err != nil {
    fmt.Println("Failed: ", err)
  } else {
    fmt.Println(instance)
  }
}

এটি @ রিপোনেট উত্তরে উপস্থাপিত ফাংশনাল অপশনগুলির সাথে সমান এবং একই সুবিধাগুলি উপভোগ করে তবে কিছু অসুবিধা রয়েছে:

  1. যদি কোনও ত্রুটি দেখা দেয় তবে এটি তাত্ক্ষণিকভাবে বাতিল হয়ে যাবে না, সুতরাং, আপনি যদি আপনার নির্মাণকারী প্রায়শই ত্রুটিগুলি প্রতিবেদন করার আশা করেন তবে এটি কিছুটা কম দক্ষ হবে।
  2. আপনাকে errভেরিয়েবল ঘোষণা করে এটি শূন্য করতে একটি লাইন ব্যয় করতে হবে।

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


এটি একটি নির্মাতা প্যাটার্ন
উমনিওব 22'18

2

আপনি একটি মানচিত্র দিয়ে নির্বিচারে নামকরণ পরামিতি পাস করতে পারেন।

type varArgs map[string]interface{}

func myFunc(args varArgs) {

    arg1 := "default" // optional default value
    if val, ok := args["arg1"]; ok {
        // value override or other action
        arg1 = val.(string) // runtime panic if wrong type
    }

    arg2 := 123 // optional default value
    if val, ok := args["arg2"]; ok {
        // value override or other action
        arg2 = val.(int) // runtime panic if wrong type
    }

    fmt.Println(arg1, arg2)
}

func Test_test() {
    myFunc(varArgs{"arg1": "value", "arg2": 1234})
}

এই পদ্ধতির বিষয়ে এখানে কিছু মন্তব্য রয়েছে: reddit.com/r/golang/comments/546g4z/…
নোবার


0

অন্য সম্ভাবনা হ'ল একটি ক্ষেত্র সহ এমন একটি কাঠামো ব্যবহার করা যা এটি বৈধ কিনা তা নির্দেশ করতে to স্কুল থেকে নাল ধরন যেমন নুলস্ট্রিং সুবিধাজনক। আপনার নিজের ধরণটি সংজ্ঞায়িত না করা ভাল, তবে আপনার যদি কাস্টম ডেটা টাইপের প্রয়োজন হয় তবে আপনি সর্বদা একই প্যাটার্নটি অনুসরণ করতে পারেন। আমি মনে করি theচ্ছিক নেসটি ফাংশন সংজ্ঞা থেকে পরিষ্কার এবং এখানে ন্যূনতম অতিরিক্ত কোড বা প্রচেষ্টা রয়েছে।

উদাহরণ হিসাবে:

func Foo(bar string, baz sql.NullString){
  if !baz.Valid {
        baz.String = "defaultValue"
  }
  // the rest of the implementation
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.