2009-11-25 10 views
7

Estoy acostumbrado a Java's String donde podemos pasar null en lugar de "" para significados especiales, como , use un valor predeterminado.¿Cómo tener una función con un parámetro de cadena anulable en Go?

En Go, la cadena es un tipo primitivo, por lo que no puedo pasar nil (nulo) a un parámetro que requiere una cadena.

podría escribir la función utilizando un tipo de puntero, como esto:

func f(s *string) 

que realiza la llamada puede llamar a esa función, ya sea como

f(nil) 

o

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

pero el siguiente es desafortunadamente no permitido:

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

¿Cuál es la mejor manera de tener un parámetro que reciba una cadena o nulo?

+0

Creo que necesitas soltar Java y acostumbrarte a la forma de Go. ¿Por qué necesitas pasar un nil en lugar de una cadena? ¿Qué quieres lograr? PD. también puedes usar fmt.Printf (* nuevo (cadena)) - que es 'cero' para el tipo cadena –

Respuesta

1

Respuesta realmente no válida: pero el valor warping en una estructura puede proporcionar algún método genérico de utilidad. (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

pensé un poco más acerca de cómo iba a poner en práctica esta usando un struct. Esto es lo que ocurrió:

type MyString struct { 
    val string; 
} 

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

A continuación, puede llamar a f así:

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

@DaveC Gracias por criticar finalmente mi respuesta de hace seis años, cuando Go tenía menos de una semana. Temía que comenzáramos a desarrollar una cultura de tomar en cuenta el contexto en el que se proporcionaron respuestas antiguas. –

+0

La pregunta llegó a la parte superior de la lista recientemente activa y miré las respuestas y vi esta respuesta incorrecta. Agregué el comentario para que otros no pierdan el tiempo probando esta no-solución votada. La fecha es irrelevante. (OMI, en lugar de ser sarcástico, simplemente debe eliminar o editar sus respuestas especulativas e incorrectas a esta pregunta). –

+0

Todos los comentarios que dejó en las respuestas a esta pregunta fueron sarcásticos e inútiles. ¿Cómo va ese dicho a señalar problemas sin sugerir soluciones? Quizás debería considerar recomendar ediciones a las respuestas existentes, o dejar una respuesta propia. (Para la posteridad/contexto, DaveC había dejado un comentario que criticaba mi "respuesta" [sus citas] sin sugerir cómo se podía mejorar.) –

-3

suelta el Java-pensar y sólo tiene que pasar f (""). A continuación, prueba usando len():

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

O bien la cadena de está vacío y tiene un significado semántico de nil caso, o bien tiene algunos datos de cadena para procesar. No puedo ver el problema con eso.

+5

El problema es que puede tener cadenas nulas como parámetros ordinarios, que no significa "el valor predeterminado". Lo que sugiere es "señalización en banda" (como usar 0 o -1 para un número entero) y es ampliamente visto como una mala idea porque puede necesitar el valor "especial" para un significado corriente. – bortzmeyer

2

Sé que estoy muy tarde para esta fiesta, pero encontré esto mientras buscaba un problema similar, y pensé en agregar mi solución para la posteridad.

Dependiendo de su caso de uso, utilizando un variadic function puede ser su amigo. Esto le permite ingresar cero o más argumentos del mismo tipo a una función, que se reciben dentro de la función como una matriz.

// 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! 

Esta solución requiere que usted sabe que va a estar pasando en un nulo en el tiempo de desarrollo; no puede simplemente llamar al f(nil) y hacer que funcione. Pero, si esto no es un problema en su caso de uso particular, podría ser una solución muy elegante que no requiera que defina ningún tipo de datos adicionales.

+0

No es elegante en absoluto que una persona que llama no tenga idea de que no debería/no puede hacer algo como 'f ("qué", "sobre", "esto") '. Sin mencionar que solo puedes usar '...' como último argumento, y que este es un uso indebido de esa característica. –

Cuestiones relacionadas