douping3891
2019-01-10 09:51
浏览 172
已采纳

如何从字面上初始化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.

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • duanqi5114 2019-01-10 10:00
    已采纳

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

    打赏 评论
  • dongyuling0312 2019-01-10 09:59

    If you have anonymous, unnamed struct types, you can only initialize them with composite literals if you repeat the struct definition. This is very inconvenient.

    So instead use named struct types, so you can use them in composite literals like this:

    Types:

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

    Then initializing it (try it on the Go Playground):

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

    See related question: Unexpected return of anonymous struct

    打赏 评论

相关推荐 更多相似问题