duannuan0074 2018-09-09 18:24
浏览 22
已采纳

在不同类型的结构之间复制公共字段

I have two structs, whose types are as follows:

type UserStruct struct {
    UserID      string            `bson:"user_id" json:"user_id"`
    Address     string            `bson:"address" json:"address"`
    Email       string            `bson:"email" json:"email"`
    CreatedAt   time.Time         `bson:"created_at" json:"created_at"`
    PhoneNumber string            `bson:"phone_number" json:"phone_number"`
    PanCard     string            `bson:"pancard" json:"pancard"`
    Details     map[string]string `json:"details"`
}

type SecretsStruct struct {
    UserID      string    `r:"user_id" json:"user_id"`
    Secrets     []string  `r:"secrets" json:secrets`
    Address     string    `r:"address" json:"address"`
    Email       string    `r:"email"json:"email"`
    CreatedAt   time.Time `r:"created_at"json:"created_at"`
    PhoneNumber string    `r:"phone_number" json:"phone_number"`
    PanCard     string    `r:"pancard" json:"pancard"`
}

I already have an instance of UserStruct. I want to copy the fields common to both structs from UserStruct to a new instance of SecretStruct, without using reflection.

  • 写回答

1条回答 默认 最新

  • doqrjrc95405 2018-09-09 18:52
    关注

    Go is a statically typed language (and is not Python). If you want to copy fields between the structs, you must either cause code to be supplied at compile time which knows how to do this, or use the reflect library to perform the operation at runtime.


    Note that I said "cause code to be supplied at compile time" because you don't have to explicitly write that code. You could use code generation to produce the copy code from the struct definitions, or from a higher-level definition (e.g. XML) which generates both the struct definition and the copying code.

    However, good Go programmers prefer clear code over clever solutions. If this is a single localized requirement, writing a code generator to avoid "boilerplate" code is almost certainly overkill; its implementation will take longer than the code to copy the structs, and the associated complexity will introduce a risk of more bugs. Similarly, reflect-based solutions are complicated, not clear, and only recommended in cases where you require a generic or extensible solution, and where this cannot be fulfilled at compile time.

    I recommend simply write the copying code, and add appropriate comments to the struct definitions and copy methods to ensure future maintainers are aware of their obligation to maintain the copy methods.


    Example

    // Define your types - bodies elided for brevity
    
    // NOTE TO MAINTAINERS: if editing the fields in these structs, ensure
    // the methods defined in source file <filename>.go are updated to
    // ensure common fields are copied between structs on instantiation.
    type UserStruct struct { ... }
    type SecretStruct struct { ... }
    
    // NewSecretStructFromUserStruct populates and returns a SecretStruct
    // from the elements common to the two types. This method must be
    // updated if the set of fields common to both structs is changed in
    // future.
    func NewSecretStructFromUserStruct(us *UserStruct) *SecretStruct {
        // You should take care to deep copy where necessary,
        // e.g. for any maps shared between the structs (not
        // currently the case).
        ss := new(SecretStruct)
        ss.UserID = us.UserID
        ss.Address = us.Address
        ss.Email = us.Email
        ss.CreatedAt = us.CreatedAt
        ss.PhoneNumber = us.PhoneNumber
        ss.PanCard = us.PanCard
        return ss
    }
    
    // You may also consider this function to be better suited as
    // a receiver method on UserStruct.
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?