golang go struct initialization default-value

golang - Cómo establecer valores predeterminados en estructuras Go



golang struct constructor (6)

Existen múltiples respuestas / técnicas para la siguiente pregunta:

  1. ¿Cómo establecer valores predeterminados para estructuras de golang?
  2. Cómo inicializar estructuras en golang

Tengo un par de respuestas pero se requiere más discusión.


  1. 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 proporcione 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

  2. 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.


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


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 unit32 // 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 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.


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 }


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"` }