私は構造体を持っています:
type Person struct {
FirstName string
LastName int
Age int
HairColor string
EyeColor string
Height string
}
そして、2つのパラメーターを取り、最初のPersonのフィールドを2番目のPersonのフィールドに更新する関数があります。
func updateFields(personA *Person, personB Person) {
personA.FirstName = personB.FirstName
personA.LastName = personB.LastName
// Don't want to change Age.
personA.HairColor = personB.HairColor
personA.EyeColor = personB.EyeColor
personA.Height = personB.Height
}
変更する値をハードコーディングする代わりに、フィールドをループして最初のPersonを更新し、「Age」フィールドを除いて2番目のPersonと同じ値にするにはどうすればよいですか?
すべてのフィールドを簡単にコピーするには、単純にのようなことができます*personA = personB
。特定のフィールドを1つだけコピーする必要がない場合(毎回同じフィールド)、そのフィールドの値を別の変数に保存し*personA = personB
、ですべてをコピーしてから、値をコピーし直すことができます。しかし、これは非常に特定の状況でのみ役立ちます。たとえば、コピーしない動的なフィールドのセットを持つことはできません。
柔軟性を高めたい場合は、以下のリフレクションのサンプルコードを使用できます。
いくつかの制限があることに注意してください。特に、設定できるのはエクスポートされたフィールドのみです。また、これらの制限をテストせず、設定できないフィールドを設定したり、そのフィールドに割り当てられない型の値を設定したりすると、reflect
パッケージは問題なく動作しpanic
ます。したがって、実際.Set(...)
にフィールドの前に多数のチェックを追加するのが賢明です。
import (
"fmt"
"reflect"
)
type Person struct {
FirstName string
LastName int
Age int
HairColor string
EyeColor string
Height string
}
func updateFields(personA *Person, personB Person) {
// .Elem() called to dereference the pointer
aVal := reflect.ValueOf(personA).Elem()
aTyp := aVal.Type()
// no .Elem() called here because it's not a pointer
bVal := reflect.ValueOf(personB)
for i := 0; i < aVal.NumField(); i++ {
// skip the "Age" field:
if aTyp.Field(i).Name == "Age" {
continue
}
// you might want to add some checks here,
// eg stuff like .CanSet(), to avoid panics
aVal.Field(i).Set(bVal.Field(i))
}
}
func main() {
b := Person{
FirstName: "Bruno",
LastName: 1,
Age: 2,
HairColor: "hello",
EyeColor: "world",
Height: "tall",
}
a := Person{}
fmt.Println(a)
updateFields(&a, b)
fmt.Println(a)
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加