Heim  >  Artikel  >  Backend-Entwicklung  >  Was ist der richtige Weg, um einer Struktur mehrere Eigenschaften bedingt zuzuweisen?

Was ist der richtige Weg, um einer Struktur mehrere Eigenschaften bedingt zuzuweisen?

WBOY
WBOYnach vorne
2024-02-06 08:05:11592Durchsuche

Was ist der richtige Weg, um einer Struktur mehrere Eigenschaften bedingt zuzuweisen?

Frageninhalt

Ich entwickle eine Parserfunktion für die GraphQL-Abfrage von be, die ich in go geschrieben habe. Im Parser habe ich Benutzerdaten, die ich mithilfe eines Eingabewerts aktualisieren möchte, der mehrere mögliche Aktualisierungseigenschaften enthält.

In Javascript geht das schnell mit Destrukturierung (Pseudo):

const mergedobj = {...oldprops, ...newprops}

Derzeit sieht meine Parser-Funktion so aus (mit gqlgen als Graphql-Go-Parser):

func (r *mutationResolver) ModifyUser(ctx context.Context, input *model.ModifyUserInput) (*model.User, error) {
    id := input.ID
    us, ok := r.Resolver.UserStore[id]
    if !ok {
        return nil, fmt.Errorf("not found")
    }

    if input.FirstName != nil {
        us.FirstName = *input.FirstName
    }

    if input.LastName != nil {
        us.LastName = *input.LastName
    }

    if input.ProfileImage != nil {
        us.ProfileImage = input.ProfileImage
    }

    if input.Password != nil {
        us.Password = *input.Password
    }

    if input.Email != nil {
        us.Email = *input.Email
    }

    if input.InTomorrow != nil {
        us.InTomorrow = input.InTomorrow
    }

    if input.DefaultDaysIn != nil {
        us.DefaultDaysIn = input.DefaultDaysIn
    }

    r.Resolver.UserStore[id] = us

    return &us, nil
}

Das fühlt sich so einfach an. Ist es in diesem Fall sinnvoll, die Strukturschlüssel zu durchlaufen? Oder gibt es ein anderes Muster, das mir fehlt?


Richtige Antwort


Verwenden Sie Funktionen, um die Boilerplate zu reduzieren:

func mergef[t any](a, b *t) {
    if b != nil {
        *a = *b
    }
}

...
mergef(&us.firstname, input.firstname)
mergef(&us.lastname, input.lastname)
...

Nutzen Sie das Reflexionspaket, um weitere Boilerplate zu reduzieren:

// merge sets fields in struct pointed to by d to 
// dereferenced fields in struct pointed to by s. 
//
// argument s must point to a struct with pointer type
// fields.   
// argument d must point to a struct with fields that 
// correspond to the fields in s: there must be a field
// in d with the same name as a field in s; the type of
// the field in s must be a pointer to the type of the field
// in d.   
func merge(d, s any) {
    sv := reflect.valueof(s).elem()
    dv := reflect.valueof(d).elem()
    for i := 0; i < sv.numfield(); i++ {
        sf := sv.field(i)
        if sf.isnil() {
            continue
        }
        df := dv.fieldbyname(sv.type().field(i).name)
        df.set(sf.elem())
    }
}

Verwenden Sie eine Funktion wie diese:

merge(us, input)

Das obige ist der detaillierte Inhalt vonWas ist der richtige Weg, um einer Struktur mehrere Eigenschaften bedingt zuzuweisen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen