Go yöntemindeki varsayılan değer


100

Go'nun işlevinde varsayılan değeri belirlemenin bir yolu var mı? Bunu belgelerde bulmaya çalışıyorum ancak bunun mümkün olduğunu belirten hiçbir şey bulamıyorum.

func SaySomething(i string = "Hello")(string){
...
}

Yanıtlar:



119

HAYIR, ancak varsayılan değeri uygulamak için başka seçenekler de vardır. Konuyla ilgili bazı güzel blog yazıları var, ancak işte bazı özel örnekler.


** Seçenek 1: ** Arayan, varsayılan değerleri kullanmayı seçer
// Both parameters are optional, use empty string for default value
func Concat1(a string, b int) string {
  if a == "" {
    a = "default-a"
  }
  if b == 0 {
    b = 5
  }

  return fmt.Sprintf("%s%d", a, b)
}

** Seçenek 2: ** Sonda tek bir isteğe bağlı parametre
// a is required, b is optional.
// Only the first value in b_optional will be used.
func Concat2(a string, b_optional ...int) string {
  b := 5
  if len(b_optional) > 0 {
    b = b_optional[0]
  }

  return fmt.Sprintf("%s%d", a, b)
}

** Seçenek 3: ** Bir yapılandırma yapısı
// A declarative default value syntax
// Empty values will be replaced with defaults
type Parameters struct {
  A string `default:"default-a"` // this only works with strings
  B string // default is 5
}

func Concat3(prm Parameters) string {
  typ := reflect.TypeOf(prm)

  if prm.A == "" {
    f, _ := typ.FieldByName("A")
    prm.A = f.Tag.Get("default")
  }

  if prm.B == 0 {
    prm.B = 5
  }

  return fmt.Sprintf("%s%d", prm.A, prm.B)
}

** Seçenek 4: ** Tam değişken bağımsız değişken ayrıştırma (javascript stili)
func Concat4(args ...interface{}) string {
  a := "default-a"
  b := 5

  for _, arg := range args {
    switch t := arg.(type) {
      case string:
        a = t
      case int:
        b = t
      default:
        panic("Unknown argument")
    }
  }

  return fmt.Sprintf("%s%d", a, b)
}

92
Ne acı. Keşke şöyle olsaydı: func Concat1(a string = 'foo', b int = 10) string {diğer modern dillerin çoğunda olduğu gibi ... Verilen örneklerden herhangi birini hemen hemen tek bir kod satırına indirgeyecekti.
Rotareti

İki farklı işlev yazma seçeneğimiz var mı ve ne bekledikleri konusunda açık olmasını arayan kişiye mi bırakıyoruz?
ProgramCpp

@ProgramCpp hayır, golang işlev aşırı yüklemesine izin vermiyor Go dilinde işlev / yöntem aşırı yüklemesi var mı?
Vusal

10

Hayır, varsayılanları belirlemenin bir yolu yoktur. Bunun yazarın tarafında biraz daha fazla zamana (ve umarım düşünerek) okunabilirliği artırmak için yapıldığına inanıyorum.

Bir "varsayılana" sahip olmanın doğru yaklaşımının, varsayılanı daha genel işleve sağlayan yeni bir işleve sahip olmak olduğunu düşünüyorum. Buna sahip olduğunuzda, kodunuz amacınıza göre daha net hale gelir. Örneğin:

func SaySomething(say string) {
    // All the complicated bits involved in saying something
}

func SayHello() {
    SaySomething("Hello")
}

Çok az çabayla, ortak bir şey yapan ve genel işlevi yeniden kullanan bir işlev yaptım. Bunu birçok kütüphanede görebilirsiniz, fmt.Printlnörneğin fmt.Print, aksi halde ne yapacağına bir satırsonu ekler . Ancak birinin kodunu okurken, dedikleri işlevle ne yapmak istedikleri açıktır. Varsayılan değerlerle, varsayılan değerin gerçekte ne olduğunu referans almak için işleve de gitmeden ne olması gerektiğini bilemeyeceğim.


Bu yanıtı beğendim ve ona katılıyorum ama yine de en azından bunu yapmanın anlaşılmaz ama deyimsel bir yolunu bulmalarını isterdim.
Sam Gomena

12
"Sadece başka işlev eklemek" yöntemlerine bir patlamaya neden olabilir argüman birden permütasyon başa gerekli metotlarda anlamlı bulunabilir ve rememberable adlarına karar yükünü gerektirir ve daha vs yöntemleri kullanmak paketleri öğrenme yükünü ekler . az. #jmtcw
MikeSchinkel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.