200

I cannot figure out how to initialize a nested struct. Find an example here: 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",
        }
    }

}
Sarun UK
  • 6,210
  • 7
  • 23
  • 48
sontags
  • 3,001
  • 3
  • 19
  • 25
  • 2
    Just learning go and had exactly the same question. You can omit element types for arrays and maps but not for nested structs. Illogical and inconvenient. Can someone explain why? – Peter Dotchev Mar 24 '18 at 06:16

10 Answers10

257

Well, any specific reason to not make Proxy its own struct?

Anyway you have 2 options:

The proper way, simply move proxy to its own struct, for example:

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

The less proper and ugly way but still works:

c := &Configuration{
    Val: "test",
    Proxy: struct {
        Address string
        Port    string
    }{
        Address: "addr",
        Port:    "80",
    },
}
OneOfOne
  • 95,033
  • 20
  • 184
  • 185
  • 7
    In the second method, can we avoid the repetitive struct definition? – Gaurav Ojha Jan 30 '17 at 06:46
  • 1
    @GauravOjha not all the way, but something like https://play.golang.org/p/n24BD3NlIR – OneOfOne Jan 30 '17 at 15:07
  • I think using an embedded type is more apt for is-a relationship. – crackerplace Jul 15 '17 at 20:53
  • 1
    as pointed out below by @sepehr you can access the variables directly using the dot notation. – snassr Jan 19 '18 at 18:32
  • 2
    What if the proxy has a field with struct as type? How to initialize them inside another nested struct? – kucinghitam Dec 20 '19 at 10:50
  • @GauravOjha I think I found the more improper way to do it without defining any type. https://play.golang.org/p/_mHcB0pBtep – proximab Aug 15 '20 at 20:11
  • 2
    The first proposal leads to name space collisions. Instead of "Proxy" you have to use "ConfigurationProxy" to avoid collisions. And if you do it correctly, you will notice that this gets more annoying with every nesting level. – ceving Mar 03 '23 at 11:54
173

If you don't want to go with separate struct definition for nested struct and you don't like second method suggested by @OneOfOne you can use this third method:

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

You can check it here: https://play.golang.org/p/WoSYCxzCF2

sepehr
  • 5,479
  • 3
  • 29
  • 33
16

Define your Proxy struct separately, outside of Configuration, like this:

type Proxy struct {
    Address string
    Port    string
}

type Configuration struct {
    Val string
    P   Proxy
}

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

See http://play.golang.org/p/7PELCVsQIc

Vitor De Mario
  • 1,129
  • 8
  • 21
12

You have this option also:

type Configuration struct {
        Val string
        Proxy
}

type Proxy struct {
        Address string
        Port    string
}

func main() {
        c := &Configuration{"test", Proxy{"addr", "port"}}
        fmt.Println(c)
}
Jose
  • 125
  • 1
  • 5
11

You also could allocate using new and initialize all fields by hand

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

See in playground: https://play.golang.org/p/sFH_-HawO_M

Ferdy Pruis
  • 1,073
  • 8
  • 9
  • Great example +1. For clarity you could add `fmt.Println(c.Val, c.Proxy.Address, c.Proxy.Port)`. –  Sep 19 '20 at 02:24
  • I'd like to add using `new()` only makes sense if you want a pointer. Otherwise just do `var c Configuration`. – Ferdy Pruis Sep 01 '22 at 19:13
9

One gotcha arises when you want to instantiate a public type defined in an external package and that type embeds other types that are private.

Example:

package animals

type otherProps{
  Name string
  Width int
}

type Duck{
  Weight int
  otherProps
}

How do you instantiate a Duck in your own program? Here's the best I could come up with:

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
  • 691
  • 7
  • 8
  • For those how forgot like me, name your struct attributes with capital letters otherwise, you will face `cannot refer to unexported field or method ` error. – tagaism Jun 17 '20 at 17:45
7

You need to redefine the unnamed struct during &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
  • 71
  • 1
  • 2
2

You can define a struct and create its object in another struct like i have done below:

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

Hope it helped you :)

1
package main

type    Proxy struct {
        Address string
        Port    string
    }

type Configuration struct {
    Proxy
    Val   string

}

func main() {

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

}
jamlee
  • 1,234
  • 1
  • 13
  • 26
0

When your configuration is something global, you can do it this way:

package main

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

func main() {
    Configuration.Val = "test"
    Configuration.Proxy.Address = "addr"
    Configuration.Proxy.Port = "80"
}
ceving
  • 21,900
  • 13
  • 104
  • 178