Existen múltiples respuestas / técnicas para la siguiente pregunta:
- ¿Cómo establecer valores predeterminados para estructuras de golang?
- Cómo inicializar estructuras en golang
Tengo un par de respuestas pero se requiere más discusión.
Existen múltiples respuestas / técnicas para la siguiente pregunta:
Tengo un par de respuestas pero se requiere más discusión.
Respuestas:
Una idea posible es escribir una función de constructor separada
//Something is the structure we work with
type Something struct {
Text string
DefaultText string
}
// NewSomething create new instance of Something
func NewSomething(text string) Something {
something := Something{}
something.Text = text
something.DefaultText = "default text"
return something
}
NewSomething
e incluso los campos Text
y DefaultText
, pero simplemente no exportar el tipo de estructura something
.
reflect.New()
, por ejemplo), no se puede esperar que sepa sobre su función de fábrica especialmente nombrada. En ese caso, y salvo que se cambie el idioma en sí , creo que solo una interfaz (que la biblioteca podría verificar) funcionaría.
Forzar un método para obtener la estructura (la forma del constructor).
Un buen diseño es hacer que su tipo no se exporte, pero proporcionar una función de constructor exportada como NewMyType () en la que pueda inicializar correctamente su estructura / tipo. También devuelva un tipo de interfaz y no un tipo concreto, y la interfaz debe contener todo lo que otros quieran hacer con su valor. Y su tipo concreto debe implementar esa interfaz, por supuesto.
Esto se puede hacer simplemente haciendo que el tipo en sí no se exporte. Puede exportar la función NewSomething e incluso los campos Text y DefaultText, pero simplemente no exporte el tipo de estructura algo
Otra forma de personalizarlo para su propio módulo es mediante el uso de una estructura de configuración para establecer los valores predeterminados (opción 5 en el enlace). Sin embargo, no es una buena manera.
Un problema con la opción 1 en respuesta de Victor Zamanian es que si el tipo no se exporta, los usuarios de su paquete no pueden declararlo como el tipo para los parámetros de función, etc. Una solución sería exportar una interfaz en lugar de struct eg
package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
Name string
Votes uint32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
return candidate{name, 0} // enforce the default value here
}
Lo que nos permite declarar los tipos de parámetros de función utilizando la interfaz Candidate exportada. La única desventaja que puedo ver de esta solución es que todos nuestros métodos deben declararse en la definición de la interfaz, pero podría argumentar que es una buena práctica de todos modos.
Votes unit32
probablemente debería serVotes uint32
Hay una manera de hacerlo con etiquetas, que permite múltiples valores predeterminados.
Suponga que tiene la siguiente estructura, con 2 etiquetas predeterminadas default0 y default1 .
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
Ahora es posible establecer los valores predeterminados.
func main() {
ptr := &A{}
Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...
Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}
Aquí está el programa completo en un patio de recreo. .
Si está interesado en un ejemplo más complejo, digamos con cortes y mapas, luego, eche un vistazo a creasty / defaultse
De https://golang.org/doc/effective_go.html#composite_literals :
A veces el valor cero no es lo suficientemente bueno y es necesario un constructor de inicialización, como en este ejemplo derivado del paquete os.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := new(File)
f.fd = fd
f.name = name
f.dirinfo = nil
f.nepipe = 0
return f
}
type Config struct {
AWSRegion string `default:"us-west-2"`
}