Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Apakah cara yang betul untuk menetapkan berbilang sifat secara bersyarat kepada struct

Apakah cara yang betul untuk menetapkan berbilang sifat secara bersyarat kepada struct

WBOY
WBOYke hadapan
2024-02-06 08:05:11624semak imbas

Apakah cara yang betul untuk menetapkan berbilang sifat secara bersyarat kepada struct

Kandungan soalan

Saya sedang membangunkan fungsi penghurai untuk pertanyaan graphql be yang saya tulis dalam go. Dalam parser, saya mempunyai data pengguna yang ingin saya kemas kini, menggunakan nilai input yang mengandungi berbilang sifat kemas kini yang mungkin.

Dalam javascript ini boleh dilakukan dengan cepat dengan memusnahkan (pseudo):

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

Pada masa ini, fungsi parser saya kelihatan seperti ini (menggunakan gqlgen sebagai 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
}

Ini terasa sangat mudah. Adakah masuk akal untuk mengulangi kekunci struct dalam kes ini? Atau adakah corak lain yang saya hilang?


Jawapan betul


Gunakan fungsi untuk mengurangkan boilerplate:

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

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

Gunakan pakej pantulan untuk mengurangkan lebih banyak boilerplate:

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

Gunakan fungsi seperti ini:

merge(us, input)

Atas ialah kandungan terperinci Apakah cara yang betul untuk menetapkan berbilang sifat secara bersyarat kepada struct. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam