Kann Go optionale Parameter haben? Oder kann ich einfach zwei Funktionen mit demselben Namen und einer unterschiedlichen Anzahl von Argumenten definieren?
Igitt, das ist ja furchtbar.
Kann Go optionale Parameter haben? Oder kann ich einfach zwei Funktionen mit demselben Namen und einer unterschiedlichen Anzahl von Argumenten definieren?
Go unterstützt nicht optionale Parameter , Standardwerte et Funktionsüberladung aber Sie können einige Tricks anwenden, um das Gleiche zu erreichen.
Teilen Sie ein Beispiel, wo Sie unterschiedliche Anzahl und Typ von Argumenten in einer Funktion haben können. Es ist ein einfacher Code für einfaches Verständnis, den Sie um Fehlerbehandlung und etwas Logik ergänzen müssen.
func student(StudentDetails ...interface{}) (name string, age int, area string) {
age = 10 //Here Age and area are optional params set to default values
area = "HillView Singapore"
for index, val := range StudentDetails {
switch index {
case 0: //the first mandatory param
name, _ = val.(string)
case 1: // age is optional param
age, _ = val.(int)
case 2: //area is optional param
area, _ = val.(string)
}
}
return
}
func main() {
fmt.Println(student("Aayansh"))
fmt.Println(student("Aayansh", 11))
fmt.Println(student("Aayansh", 15, "Bukit Gombak, Singapore"))
}
Ich bin ein wenig spät dran, aber wenn Sie fließende Schnittstellen mögen, könnten Sie Ihre Setter für verkettete Aufrufe wie diese entwerfen:
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
}
Und dann nennen Sie es so:
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)
}
}
Dies ist ähnlich wie die Funktionelle Optionen Idiom auf @Ripounet Antwort vorgestellt und genießt die gleichen Vorteile, hat aber einige Nachteile:
err
und die Variable auf Null setzen.Es gibt jedoch einen möglichen kleinen Vorteil, diese Art von Funktionsaufrufen sollte für den Compiler einfacher zu inline sein, aber ich bin wirklich kein Spezialist.
Meh. Was passiert, wenn A einen Fehler produziert, aber nicht B, C, D, und A ist Ihnen egal?
@ Du könntest die Aufrufe einfach trennen, z.B. zuerst alles bauen, was dich interessiert, dann die Fehler prüfen und dann einstellen, was du nicht prüfen willst. Oder wenn Sie derjenige sind, der den Konstruktor in erster Linie schreibt, können Sie die Fehler einfach intern ignorieren und erhalten keinen *Fehler für die Einstellung von A.
Am Ende habe ich eine Kombination aus einer Struktur von params und variadic args verwendet. Auf diese Weise musste ich die bestehende Schnittstelle, die von mehreren Diensten genutzt wurde, nicht ändern und mein Dienst konnte bei Bedarf zusätzliche Parameter übergeben. Beispielcode im Golang-Spielplatz: https://play.golang.org/p/G668FA97Nu
Eine andere Möglichkeit wäre die Verwendung einer Struktur mit einem Feld, das angibt, ob sie gültig ist. Die Null-Typen aus Sql wie z.B. NullString sind praktisch. Es ist schön, wenn man nicht seinen eigenen Typ definieren muss, aber falls man einen benutzerdefinierten Datentyp benötigt, kann man immer dem gleichen Muster folgen. Ich denke, die Optionalität ist aus der Funktionsdefinition ersichtlich, und es gibt nur minimalen zusätzlichen Code oder Aufwand.
Ein Beispiel:
func Foo(bar string, baz sql.NullString){
if !baz.Valid {
baz.String = "defaultValue"
}
// the rest of the implementation
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
1 Stimmen
In diesem Zusammenhang: So kann man obligatorische Parameter erzwingen, wenn man variadic als optionale Parameter verwendet: Ist es möglich, Kompilierzeit Fehler mit benutzerdefinierten Bibliothek in Golang auslösen?
110 Stimmen
Google hat eine schreckliche Entscheidung getroffen, denn manchmal hat eine Funktion einen 90%igen Anwendungsfall und dann einen 10%igen Anwendungsfall. Das optionale Argument ist für diese 10 % des Anwendungsfalls gedacht. Vernünftige Standardwerte bedeuten weniger Code, weniger Code bedeutet mehr Wartbarkeit.
7 Stimmen
Ich halte den Verzicht auf optionale Parameter für eine gute Entscheidung. Ich habe gesehen, dass optionale Parameter in C++ ziemlich stark missbraucht wurden - 40+ Argumente. Es ist sehr fehleranfällig, die Argumente durchzuzählen und sicherzustellen, dass man das richtige angibt, besonders ohne benannte Parameter. Viel besser ist es, eine Struktur zu verwenden, wie von @deamon erwähnt.
5 Stimmen
@Jonathan es gibt mehrere Möglichkeiten, damit umzugehen. Eine Möglichkeit ist, eine Struktur mit allen Parametern für die Funktion zu übergeben. Dies hat den zusätzlichen Vorteil, dass man benannte Parameter hat (klarer als Positionsparameter) und alle Parameter, die nicht übergeben werden, ihren Standardwert haben. Und natürlich kann man auch einfach eine Wrapper-Funktion erstellen, die den Standardwert an die vollständige Funktion übergibt. z.B. Query und QueryWithContext
3 Stimmen
@Falco moderne IDEs generieren automatisch benannte Parameter aus der Semantik, so dass es nicht ideal erscheint, den Programmierer zu zwingen, seinen Code umzugestalten, um etwas zu tun, was eine IDE für Sie tun kann
0 Stimmen
@Jonathan Die meisten IDEs zeigen beim beiläufigen Lesen von Code keine Parameternamen an. Normalerweise muss man den Funktionsaufruf auswählen, um die Signatur zu sehen, und dann die tatsächlichen Parameter der Liste der Parameternamen im Kopf zuordnen. Die meisten Codestile / Clean Code Papers raten auch von langen Parameterlisten in Funktionen ab. Man sollte entweder eine Struktur übergeben oder ein objektorientiertes Design verwenden, wenn man eine Funktion mit vielen Parametern hat.
1 Stimmen
@Falco Ich habe ausdrücklich erklärt modern IDEs. Die meisten Legacy-IDEs haben das von Ihnen erwähnte Verhalten.
2 Stimmen
@Jonathan es scheint nicht zu funktionieren out of the box in VS Code, Visual Studio, IntelliJ, Atom oder Sublime. Auf welche IDE beziehen Sie sich, oder gibt es Erweiterungen/Einstellungen, die dies ermöglichen?