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

WBOY
Lepaskan: 2024-02-06 08:05:11
ke hadapan
627 orang telah melayarinya

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
}
Salin selepas log masuk

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)
...
Salin selepas log masuk

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())
    }
}
Salin selepas log masuk

Gunakan fungsi seperti ini:

merge(us, input)
Salin selepas log masuk

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!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan