Ініціалізуйте вкладену структуру


124

Я не можу зрозуміти, як ініціалізувати вкладену структуру. Знайдіть приклад тут: 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
Щойно навчання пішло і було саме таке питання. Ви можете опускати типи елементів для масивів і карт, але не для вкладених структур. Нелогічне і незручне. Може хтось пояснить, чому?
Петро Дотчев

Відповіді:


177

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

У будь-якому випадку у вас є два варіанти:

Правильним способом просто перемістити проксі до власної структури, наприклад:

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

1
Чи можна уникнути другого методу визначення структури, що повторюється?
Gaurav Ojha

@GauravOjha не зовсім, але щось на кшталт play.golang.org/p/n24BD3NlIR
OneOfOne

Я думаю, що використання вбудованого типу є більш підходящим для стосунків.
crackerplace

як зазначено нижче від @sepehr, ви можете отримати доступ до змінних безпосередньо, використовуючи позначення крапок.
snassr

Що робити, якщо проксі-сервер має поле з структура як тип? Як ініціалізувати їх всередині іншої вкладеної структури?
кукінгхітам

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


8
Вау, фактична відповідь на питання, як ініціалізувати вкладені структури.
Макс

1
Це насправді досить добре, але було б краще, якби ми могли це зробити за один рядок!
Гаурав Оджа

1
Я шукав спосіб, де вам не потрібно було робити c.Proxy.Address = `127.0.0.1` c.Proxy.Port = `8080` Чи є спосіб ініціалізувати ці значення під час &Configuration{}призначення?
Матей Феліпе

1
@MatheusFelipe ви можете, але тоді вам доведеться визначити Proxyйого як власну структуру, дивіться перший метод у відповіді від @OneOfOne
sepehr

ІМО, це краще, ніж прийнята відповідь.
domoarigato


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

Так чи те ж саме з полем
Pierrick HYMBERT

Що робити, якщо Proxyце масив?
Ertuğrul Altınboğa

9

Один gotcha виникає, коли ви хочете створити загальнодоступний тип, визначений у зовнішньому пакеті, і цей тип вбудовує інші типи, які є приватними.

Приклад:

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

Для тих, хто забув, як я, інакше назви свої атрибути структури великими літерами, ви зіткнетеся з 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.