Nilai default dalam metode Go

99

Apakah ada cara untuk menentukan nilai default dalam fungsi Go? Saya mencoba menemukan ini di dokumentasi tetapi saya tidak dapat menemukan apa pun yang menentukan bahwa ini bahkan mungkin.

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

Jawaban:

117

TIDAK, tetapi ada beberapa opsi lain untuk menerapkan nilai default. Ada beberapa posting blog yang bagus tentang subjek ini, tetapi berikut ini beberapa contoh spesifik.


** Opsi 1: ** Penelepon memilih untuk menggunakan nilai default
// 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)
}

** Opsi 2: ** Satu parameter opsional di bagian akhir
// 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)
}

** Opsi 3: ** Sebuah config struct
// 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)
}

** Opsi 4: ** Penguraian argumen variadic penuh (gaya javascript)
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)
}
kepala sekolah
sumber
91
Sakit sekali. Saya berharap seperti itu: func Concat1(a string = 'foo', b int = 10) string {seperti di kebanyakan bahasa modern lainnya ... Ini akan mengurangi sebagian besar contoh yang diberikan menjadi satu baris kode.
Rotareti
Apakah kita memiliki opsi untuk menulis dua fungsi yang berbeda dan menyerahkan kepada pemanggil untuk menjelaskan secara eksplisit tentang apa yang mereka harapkan.
ProgramCpp
@ProgramCpp tidak, golang tidak mengizinkan kelebihan beban fungsi Apakah bahasa Go memiliki kelebihan beban fungsi / metode?
Vusal
9

Tidak, tidak ada cara untuk menentukan default. Saya percaya ini dilakukan dengan tujuan untuk meningkatkan keterbacaan, dengan mengorbankan lebih banyak waktu (dan, semoga, pemikiran) di pihak penulis.

Saya pikir pendekatan yang tepat untuk memiliki "default" adalah memiliki fungsi baru yang memasok default itu ke fungsi yang lebih umum. Setelah ini, kode Anda menjadi lebih jelas tentang maksud Anda. Sebagai contoh:

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

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

Dengan sedikit usaha, saya membuat fungsi yang melakukan hal umum dan menggunakan kembali fungsi generik. Anda dapat melihat ini di banyak pustaka, fmt.Printlnmisalnya hanya menambahkan baris baru ke apa yang fmt.Printseharusnya dilakukan. Namun, saat membaca kode seseorang, jelas apa yang ingin mereka lakukan dengan fungsi yang mereka panggil. Dengan nilai default, saya tidak akan tahu apa yang seharusnya terjadi tanpa juga pergi ke fungsi untuk mereferensikan apa nilai default sebenarnya.

Dave
sumber
Saya suka dan setuju dengan jawaban ini tetapi sialnya saya masih berharap mereka setidaknya memiliki cara yang bodoh tetapi idiomatis untuk melakukannya.
Sam Gomena
12
The "hanya menambahkan fungsi lain" argumen dapat mengakibatkan ledakan metode yang diperlukan untuk menangani beberapa permutasi, membutuhkan beban memutuskan nama-nama bermakna, ditemukan dan rememberable untuk metode mereka, dan menambah beban belajar paket yang menggunakan metode yang lebih vs kurang. #jmtcw
MikeSchinkel