Инициализировать вложенную структуру

125

Я не могу понять, как инициализировать вложенную структуру. Пример можно найти здесь: 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",
        },
    }

}
sontags
источник
1
Просто учился, и возник точно такой же вопрос. Вы можете опускать типы элементов для массивов и карт, но не для вложенных структур. Нелогично и неудобно. Может кто-нибудь объяснить почему?
Peter Dotchev

Ответы:

178

Ну, а какая конкретная причина не делать Proxy своей собственной структурой?

В любом случае у вас есть 2 варианта:

Правильный способ, просто переместите прокси в его собственную структуру, например:

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)
}

Менее правильный и уродливый способ, но все же работает:

c := &Configuration{
    Val: "test",
    Proxy: struct {
        Address string
        Port    string
    }{
        Address: "addr",
        Port:    "80",
    },
}
OneOfOne
источник
1
Можем ли мы избежать повторяющегося определения структуры во втором методе?
Gaurav Ojha
@GauravOjha не до конца, но что-то вроде play.golang.org/p/n24BD3NlIR
OneOfOne
Я думаю, что использование встроенного типа более уместно для отношений.
crackerplace
как указано ниже @sepehr, вы можете получить доступ к переменным напрямую, используя точечную нотацию.
snassr
Что, если у прокси есть поле со структурой как тип? Как инициализировать их внутри другой вложенной структуры?
kucinghitam
90

Если вы не хотите использовать отдельное определение структуры для вложенной структуры и вам не нравится второй метод, предложенный @OneOfOne, вы можете использовать этот третий метод:

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

Вы можете проверить это здесь: https://play.golang.org/p/WoSYCxzCF2

Sepehr
источник
8
Вау, реальный ответ на вопрос, как инициализировать вложенные структуры.
Макс
1
Это действительно неплохо, но было бы лучше, если бы мы могли сделать это в одну строку!
Gaurav Ojha
1
Я искал способ, при котором вам не нужно было бы делать c.Proxy.Address = `127.0.0.1` c.Proxy.Port = `8080` это. Есть ли способ инициализировать эти значения во время &Configuration{}присваивания?
Матеус Фелипе
1
@MatheusFelipe вы можете, но тогда вы должны определить Proxyкак свою собственную структуру, см. Первый метод в ответе @OneOfOne
sepehr
ИМО, это лучше, чем принятый ответ.
domoarigato
14

Определите свою Proxyструктуру отдельно, за пределами Configuration, например:

type Proxy struct {
    Address string
    Port    string
}

type Configuration struct {
    Val string
    P   Proxy
}

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

См. Http://play.golang.org/p/7PELCVsQIc

Витор де Марио
источник
Что, если P Proxyэто массив?
Эртугрул Алтынбога,
10

У вас также есть такая возможность:

type Configuration struct {
        Val string
        Proxy
}

type Proxy struct {
        Address string
        Port    string
}

func main() {
        c := &Configuration{"test", Proxy{"addr", "port"}}
        fmt.Println(c)
}
Хосе
источник
Да или то же самое со вторым типом поля
Пьеррик ГИМБЕРТ
Что, если Proxyэто массив?
Эртугрул Алтынбога,
9

Одна проблема возникает, когда вы хотите создать экземпляр общедоступного типа, определенного во внешнем пакете, и этот тип включает в себя другие частные типы.

Пример:

package animals

type otherProps{
  Name string
  Width int
}

type Duck{
  Weight int
  otherProps
}

Как создать экземпляр Duckв своей собственной программе? Вот лучшее, что я мог придумать:

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"
}
dvdplm
источник
Для тех, кто забыл, как я, назовите свои атрибуты структуры заглавными буквами, иначе вы столкнетесь с cannot refer to unexported field or method ошибкой.
тагайзм
5

Вы также можете выделить, используя newи инициализировать все поля вручную

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

Смотрите на детской площадке: https://play.golang.org/p/sFH_-HawO_M

Ферди Пруис
источник
2

Вы можете определить структуру и создать ее объект в другой структуре, как я сделал ниже:

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)
}

Надеюсь, это вам помогло :)

Випин Гупта
источник
2

Вам нужно переопределить безымянную структуру во время &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

lizhenpeng
источник