GAE/Go Datastore 중첩된 구조체 저장(더 slice를 결합한 경우)

(2020.8.12 추가)
본 기사는 GAE/Go 1st gen의 appengine/datastore 패키지를 사용했을 경우의 내용이 되고 있습니다.
Client Library( cloud.google.com/go/datastore 패키지)를 사용하면 기본 동작이 다릅니다. Client Library의 경우 구조체 태그에 flattten를 지정하면 이 기사와 같은 거동이 됩니다.

GAE/Go Datastore API는 중첩 구조를 저장할 수 있습니다.
이번, 구조체에 slice가 얽힌 경우에 어떤 형태로 보존되는지가 흥미 있었으므로 시험해 보았습니다.

단일 구조체 중첩



우선은 간단하게, 구조체에 구조체를 중첩.

구조체 정의


type Inner struct {
    Name  string
    Value int
}

type Outer struct {
    Name  string
    Inner Inner
}

저장


    c := appengine.NewContext(r)

    key := datastore.NewKey(c, "Outer", "test", 0, nil)
    outer := Outer{
        Name: "outer",
        Inner: Inner{
            Name:  "inner",
            Value: 999,
        },
    }

    if _, err := datastore.Put(c, key, &outer); err != nil {
        return err
    }

결과




Inner.Name Inner.Value 라는 dot 단락의 별개의 프로퍼티에 전개됩니다.

구조체의 slice



구조체의 slice를 필드로서 가지는 케이스.

구조체 정의


type Inner struct {
    Name  string
    Value int
}

type Outer struct {
    Name   string
    Inners []Inner
}

저장


    key := datastore.NewKey(c, "Outer", "test", 0, nil)
    outer := Outer{
        Name: "outer",
        Inners: []Inner{
            Inner{
                Name:  "inner1",
                Value: 111,
            },
            Inner{
                Name:  "inner1",
                Value: 222,
            },
        },
    }

    if _, err := datastore.Put(c, key, &outer); err != nil {
        return err
    }


결과




Inners.Name , Inners.Value 각각이 목록 속성으로 확장되었습니다. (같은 length가 되는 것이군요)

중첩된 구조체 안에 slice



중첩된 구조체가 slice 필드를 가지는 경우입니다.

구조체 정의


type Inner struct {
    Names  []string
    Values []int
}

type Outer struct {
    Name  string
    Inner Inner
}

저장


    key := datastore.NewKey(c, "Outer", "test", 0, nil)
    outer := Outer{
        Name: "outer",
        Inner: Inner{
            Names:  []string{"inner1-1", "inner1-2"},
            Values: []int{11, 12, 13},
        },
    }

    if _, err := datastore.Put(c, key, &outer); err != nil {
        return err
    }

결과





중첩 구조 slice의 경우와 동일한 형식으로 확장되었습니다. 이 경우 length는 동일하지 않습니다.
과연 잘 됐다.

slice 안에 더 slice



slice 중간 구조체에 더 slice가 있다면 어떻게 전개될까요?

구조체 정의


type Inner struct {
    Names  []string
    Values []int
}

type Outer struct {
    Name   string
    Inners []Inner
}

저장


    key := datastore.NewKey(c, "Outer", "test", 0, nil)
    outer := Outer{
        Name: "outer",
        Inners: []Inner{
            Inner{
                Names:  []string{"inner1-1", "inner1-2"},
                Values: []int{11, 12},
            },
            Inner{
                Names:  []string{"inner2-1", "inner2-2"},
                Values: []int{21, 22, 23},
            },
        },
    }

    if _, err := datastore.Put(c, key, &outer); err != nil {
        return err
    }


결과


datastore: flattening nested structs leads to a slice of slices: field "Inners" 라는 오류가 발생했습니다.
프로퍼티 트리중, 다른 계층에 slice가 있으면 에러가 되는군요.

요약



너무 복잡한 데이터 구조에 사용하는 것은 엄격한 것 같습니다만, 프로퍼티를 그룹핑할 정도로 사용하기에는 매우 편리해요\(^o^)/

참고

좋은 웹페이지 즐겨찾기