Избегайте дублирования кода при переписывании методов Scan и Value для каждого типа при использовании команды go sql - PullRequest
0 голосов
/ 05 сентября 2018

Golan SQL плюс Gorp ожидают, что все типы включают метод Scan и Value, прикрепленный к типу для чтения строк в структуру. Это добавляет много шаблонного кода в мой проект, даже если методы могут быть обобщены, потому что я пишу JSON в эти столбцы.

type Type1 struct {
 Type2 Type2
 Type3 Type3
 Type4 Type4
}

type Type2 struct { some primitives... }
type Type3 struct { some primitives... }
type Type4 struct { some primitives... }


func (q Type2) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Type2) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}

func (q Type3) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Type3) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}

func (q Type4) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Type4) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}

Есть ли способ избежать определения всех этих идентичных значений и методов сканирования для каждой из моих структур?

Таблица должна выглядеть так:

Table: Type1
-----------------------
ROW   Type2                Type3               Type4
1     {"name": "MyName"}   {"other": "bla"}    {"other": "bla"}

Я пытался использовать композицию, так как @danicheeta порекомендовал:

type Base struct {} 
type Type2 struct { Base, some primitives... }

func (q Base) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Base) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}

Но если я выполню вставку в базу данных, результат будет:

Table: Type1
-----------------------
ROW   Type2                Type3               Type4
1     {}                   {}                  {}

Аналогично, если я уже вставил «вручную» в базу данных, это:

Table: Type1
    -----------------------
    ROW   Type2                Type3               Type4
    1     {"name": "MyName"}   {"other": "bla"}    {"other": "bla"}

И попробуйте сделать select * from Type1 Я получаю:

Type1: {
   Type2: {}
   Type3: {}
   Type4: {}
}

1 Ответ

0 голосов
/ 05 сентября 2018

вот решение:

type Base struct {}

type Type2 struct { Base, some primitives... }
type Type3 struct { Base, some primitives... }
type Type4 struct { Base, some primitives... }

func (q Base) Value() (driver.Value, error) {
    return json.Marshal(q)
}

func (q *Base) Scan(src interface{}) error {
    source, _ := src.([]byte)
    if string(source) == "null" {
        return nil
    }
    return json.Unmarshal(source, q)
}

обратите внимание, что Base, заложенный в структуры, не должен иметь перед собой переменную (я имею в виду type Type2 struct { b Base, some primitives... })

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...