Inicializar una estructura anidada


124

No puedo averiguar cómo inicializar una estructura anidada. Encuentre un ejemplo aquí: http://play.golang.org/p/NL6VXdHrjh

package main

type Configuration struct {
    Val   string
    Proxy struct {
        Address string
        Port    string
    }
}

func main() {

    c := &Configuration{
        Val: "test",
        Proxy: {
            Address: "addr",
            Port:    "80",
        },
    }

}

1
Acabo de aprender a ir y tenía exactamente la misma pregunta. Puede omitir tipos de elementos para matrices y mapas, pero no para estructuras anidadas. Ilógico e inconveniente. ¿Alguien puede explicar por qué?
Peter Dotchev

Respuestas:


177

Bueno, ¿alguna razón específica para no hacer de Proxy su propia estructura?

De todos modos tienes 2 opciones:

La forma correcta, simplemente mueva el proxy a su propia estructura, por ejemplo:

type Configuration struct {
    Val string
    Proxy Proxy
}

type Proxy struct {
    Address string
    Port    string
}

func main() {

    c := &Configuration{
        Val: "test",
        Proxy: Proxy{
            Address: "addr",
            Port:    "port",
        },
    }
    fmt.Println(c)
    fmt.Println(c.Proxy.Address)
}

La forma menos adecuada y fea, pero aún funciona:

c := &Configuration{
    Val: "test",
    Proxy: struct {
        Address string
        Port    string
    }{
        Address: "addr",
        Port:    "80",
    },
}

1
En el segundo método, ¿podemos evitar la definición de estructura repetitiva?
Gaurav Ojha

@GauravOjha no del todo, sino algo como play.golang.org/p/n24BD3NlIR
OneOfOne

Creo que usar un tipo incrustado es más apto para una relación is-a.
crackerplace

como se indica a continuación por @sepehr, puede acceder a las variables directamente utilizando la notación de puntos.
snassr

¿Qué pasa si el proxy tiene un campo con estructura como tipo? ¿Cómo inicializarlos dentro de otra estructura anidada?
kucinghitam

90

Si no desea ir con una definición de estructura separada para una estructura anidada y no le gusta el segundo método sugerido por @OneOfOne, puede usar este tercer método:

package main
import "fmt"
type Configuration struct {
    Val   string
    Proxy struct {
        Address string
        Port    string
    }
}

func main() {
    c := &Configuration{
        Val: "test",
    }

    c.Proxy.Address = `127.0.0.1`
    c.Proxy.Port = `8080`
}

Puedes consultarlo aquí: https://play.golang.org/p/WoSYCxzCF2


8
Vaya, una respuesta real a la pregunta de cómo inicializar estructuras anidadas .
Máximo

1
Esto es realmente bastante bueno, ¡pero hubiera sido mejor si pudiéramos hacerlo en una línea!
Gaurav Ojha

1
Estaba buscando una forma en la que no tendrías que hacerlo. c.Proxy.Address = `127.0.0.1` c.Proxy.Port = `8080` ¿Hay alguna forma de inicializar esos valores durante la &Configuration{}asignación?
Matheus Felipe

1
@MatheusFelipe puede, pero luego debe definir Proxycomo su propia estructura, vea el primer método en la respuesta de @OneOfOne
sepehr

En mi opinión, esto es mejor que la respuesta aceptada.
domoarigato


10

También tienes esta opción:

type Configuration struct {
        Val string
        Proxy
}

type Proxy struct {
        Address string
        Port    string
}

func main() {
        c := &Configuration{"test", Proxy{"addr", "port"}}
        fmt.Println(c)
}

Sí o lo mismo con el segundo tipo de campo
Pierrick HYMBERT

¿Y si Proxyes una matriz?
Ertuğrul Altınboğa

9

Un problema surge cuando desea instanciar un tipo público definido en un paquete externo y ese tipo incrusta otros tipos que son privados.

Ejemplo:

package animals

type otherProps{
  Name string
  Width int
}

type Duck{
  Weight int
  otherProps
}

¿Cómo crea una instancia Ducken su propio programa? Aquí está lo mejor que se me ocurrió:

package main

import "github.com/someone/animals"

func main(){
  var duck animals.Duck
  // Can't instantiate a duck with something.Duck{Weight: 2, Name: "Henry"} because `Name` is part of the private type `otherProps`
  duck.Weight = 2
  duck.Width = 30
  duck.Name = "Henry"
}

Para aquellos que se han olvidado como yo, nombre sus atributos de estructura con letras mayúsculas; de lo contrario, se encontrará con un cannot refer to unexported field or method error.
tagaism

5

También puede asignar newe inicializar todos los campos a mano

package main

type Configuration struct {
    Val   string
    Proxy struct {
        Address string
        Port    string
    }
}

func main() {
    c := new(Configuration)
    c.Val = "test"
    c.Proxy.Address = "addr"
    c.Proxy.Port = "80"
}

Ver en el patio de recreo: https://play.golang.org/p/sFH_-HawO_M


2

Puede definir una estructura y crear su objeto en otra estructura como lo he hecho a continuación:

package main

import "fmt"

type Address struct {
    streetNumber int
    streetName   string
    zipCode      int
}

type Person struct {
    name    string
    age     int
    address Address
}

func main() {
    var p Person
    p.name = "Vipin"
    p.age = 30
    p.address = Address{
        streetName:   "Krishna Pura",
        streetNumber: 14,
        zipCode:      475110,
    }
    fmt.Println("Name: ", p.name)
    fmt.Println("Age: ", p.age)
    fmt.Println("StreetName: ", p.address.streetName)
    fmt.Println("StreeNumber: ", p.address.streetNumber)
}

Espero que te haya ayudado :)


2

Necesita redefinir la estructura sin nombre durante &Configuration{}

package main

import "fmt"

type Configuration struct {
    Val   string
    Proxy struct {
        Address string
        Port    string
    }
}

func main() {

    c := &Configuration{
        Val: "test",
        Proxy: struct {
            Address string
            Port    string
        }{
            Address: "127.0.0.1",
            Port:    "8080",
        },
    }
    fmt.Println(c)
}

https://play.golang.org/p/Fv5QYylFGAY

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.