Search code examples
gostructcomposite-literals

How to literally initialize multi-level nested structs in GO?


I am trying to literally initialize the following struct in GO:

This is the struct:

type tokenRequest struct {
    auth struct {
        identity struct {
            methods  []string
            password struct {
                user struct {
                    name   string
                    domain struct {
                        id string
                    }
                    password string
                }
            }
        }
    }
}

And this is my code:

req := &tokenRequest{
    auth: struct {
        identity: struct {
            methods: []string{"password"},
            password: {
                user: {
                    name: os.Username,
                    domain: {
                        id: "default",
                    },
                    password: os.Password,
                },
            },
        },
    },
}

https://play.golang.org/p/e8Yuk-37_nN

Can I initialize without defining all the nested structs separately (i.e. auth, identity, password, user)

Thank you.


Solution

  • You can, but you're going to be typing a lot:

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    type tokenRequest struct {
        auth struct {
            identity struct {
                methods  []string
                password struct {
                    user struct {
                        name   string
                        domain struct {
                            id string
                        }
                        password string
                    }
                }
            }
        }
    }
    
    func main() {
        s := tokenRequest{
            auth: struct {
                identity struct {
                    methods  []string
                    password struct {
                        user struct {
                            name   string
                            domain struct {
                                id string
                            }
                            password string
                        }
                    }
                }
            }{
                identity: struct {
                    methods  []string
                    password struct {
                        user struct {
                            name   string
                            domain struct {
                                id string
                            }
                            password string
                        }
                    }
                }{
                    methods: []string{http.MethodGet, http.MethodPost},
                    password: struct {
                        user struct {
                            name   string
                            domain struct {
                                id string
                            }
                            password string
                        }
                    }{
                        user: struct {
                            name   string
                            domain struct {
                                id string
                            }
                            password string
                        }{
                            name: "username",
                            domain: struct {
                                id string
                            }{
                                id: "domain id",
                            },
                            password: "password",
                        },
                    },
                },
            },
        }
    
        fmt.Printf("%+v\n", s)
    }
    

    You have to tell Go what type of variable you're initializing, so you just define the same anonymous struct, slowly but surely removing a level each time.

    For this reason, it's better to use named structs so you don't have to repeat yourself.