2009-11-25 3 views
7

Je suis habitué à Java's String où nous pouvons passer null plutôt que "" pour des significations spéciales, comme utiliser une valeur par défaut.Comment avoir une fonction avec un paramètre de chaîne Nullable dans Go?

Dans Go, chaîne est un type primitif, donc je ne peux pas passer nil (null) à un paramètre qui nécessite une chaîne.

Je pourrais écrire la fonction en utilisant le type de pointeur, comme ceci:

func f(s *string) 

si l'appelant peut appeler cette fonction soit comme

f(nil) 

ou

// not so elegant 
temp := "hello"; 
f(&temp) 

mais ce qui suit malheureusement pas permis:

// elegant but disallowed 
f(&"hello"); 

Quelle est la meilleure façon d'avoir un paramètre qui reçoit soit une chaîne ou nil?

+0

Je crois que vous devez abandonner Java et vous habituer à aller à la place. Pourquoi avez-vous besoin de passer un zéro au lieu d'une chaîne? Que veux-tu accomplir? ps. vous pouvez également utiliser fmt.Printf (* new (string)) - qui est 'zéro' pour la chaîne de caractères –

Répondre

1

N'attendez pas vraiment la réponse: mais la valeur de déformation dans une structure peut fournir une méthode d'utilité générique. (Haskell Maybe?)

//#maybe.go 
package maybe 

import "log" 

type MayHaveValue struct { 
IsValue bool; 
} 

func (this MayHaveValue) IsJust() bool { 
return this.IsValue 
} 

type AString struct { 
MayHaveValue; 
Value string; 
} 

func String(aString string) AString { 
return AString{MayHaveValue{true}, aString} 
} 

var NoString AString = AString{MayHaveValue{false}, ""} 

func (this AString) String() (value string) { 
if this.IsJust() == true { 
    value = this.Value; 
} else { 
    log.Crash("Access to non existent maybeString value"); 
} 
return; 
} 

func (this AString) OrDefault(defaultString string) (value string) { 
if this.IsJust() { 
    value = this.Value; 
} else { 
    value = defaultString; 
} 
return; 
} 

//#main.go 
package main 

import "fmt" 
import "maybe" 

func say(canBeString maybe.AString) { 
if canBeString.IsJust() { 
    fmt.Printf("Say : %v\n", canBeString.String()); 
} else { 
    fmt.Print("Nothing to say !\n"); 
} 
} 

func sayMaybeNothing (canBeString maybe.AString) { 
fmt.Printf("Say : %v\n", canBeString.OrDefault("nothing")); 
} 

func main() { 
aString := maybe.String("hello"); 
say(aString); 
sayMaybeNothing(aString); 
noString := maybe.NoString; 
say(noString); 
sayMaybeNothing(noString); 
} 
4

Je pensais un peu plus sur la façon dont je mettre en œuvre cette aide d'un struct. Voici ce que je suis venu avec:

type MyString struct { 
    val string; 
} 

func f(s MyString) { 
    if s == nil { 
     s = MyString{"some default"}; 
    } 
    //do something with s.val 
} 

Ensuite, vous pouvez appeler f comme ceci:

f(nil); 
f(MyString{"not a default"}); 
+1

@DaveC Merci d'avoir finalement critiqué ma réponse de six ans, à une époque où Go avait moins d'une semaine. J'avais peur que nous commencions à développer une culture de prise en compte du contexte dans lequel les anciennes réponses étaient fournies. –

+0

La question est venue en haut de la liste récemment active et j'ai regardé les réponses et j'ai vu cette réponse incorrecte. J'ai ajouté le commentaire pour que les autres ne perdent pas de temps à essayer cette solution non votée. La date n'est pas pertinente. (OMI, au lieu d'être sarcastique, vous devez simplement supprimer ou modifier vos réponses spéculatives et incorrectes à cette question). –

+0

Chaque commentaire que vous avez laissé sur les réponses à cette question était sarcastique et peu utile. Comment ce dicton peut-il signaler des problèmes sans suggérer des solutions? Vous devriez peut-être envisager de recommander des modifications aux réponses existantes ou de laisser une réponse de votre choix. (Pour postérité/contexte, DaveC avait laissé un commentaire qui critiquait ma "réponse" [ses citations] sans suggérer comment il pourrait être amélioré.) –

-3

lâche Java-penser et passer juste f (""). Ensuite, test à l'aide len():

func f (string str) { si len (str)> 0 {... } else { ...} }

Soit la chaîne est vide et a une signification sémantique de votre cas, ou bien a des données de chaîne à traiter. Je ne vois pas le problème avec ça.

+5

Le problème est que vous pouvez avoir des chaînes nulles en tant que paramètres ordinaires, ne signifiant pas "le défaut". Ce que vous proposez est "signalisation dans la bande" (comme utiliser 0 ou -1 pour un entier) et est largement considéré comme une mauvaise idée, car vous pourriez avoir besoin de la valeur "spéciale" pour un sens ordinaire. – bortzmeyer

2

Je sais que je suis super en retard pour cette fête, mais je l'ai trouvé en cherchant un problème similaire, et j'ai pensé que j'ajouterais ma solution pour la postérité.

En fonction de votre utilisation, l'utilisation d'un variadic function peut être votre ami. Cela vous permet d'entrer zéro ou plusieurs arguments du même type à une fonction, qui sont reçus dans la fonction en tant que tableau.

// My variadic function 
func f(s string...) { 
    if length(s) == 0 { 
    // We got a NULL 
    fmt.Println("default value") 
    } else { 
    // We got a value 
    fmt.Println(s[0]) 
    } 
} 

f() // works! 
f("has a value") // works! 

Cette solution nécessite que vous sachiez que vous allez passer à zéro au moment du développement; vous ne pouvez pas simplement appeler f(nil) et le faire fonctionner. Mais, si ce n'est pas un problème dans votre cas d'utilisation particulier, cela pourrait être une solution très élégante qui ne nécessite pas de définir des types de données supplémentaires.

+0

Ce n'est pas du tout élégant en ce sens qu'un appelant n'a aucune idée qu'il ne devrait pas/ne peut pas faire quelque chose comme '' ("quoi", "environ", "ceci") '. Sans oublier que vous ne pouvez utiliser que '...' comme dernier argument, et que c'est une mauvaise utilisation de cette fonctionnalité. –

Questions connexes