Mając tę strukturę tabeli:Confused o niestandardowych typów w SQL po sql.DB.Exec
CREATE TABLE `tableName` (
`Id` int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`Status` enum('pending','rejected','sent','invalid') NOT NULL,
`Body` varchar(255) NULL
) ENGINE='MyISAM' COLLATE 'utf8_general_ci';
mam to (nie zakończyć) Kod działa dobrze:
type StatusEnum string
const (
STATUS_PENDING StatusEnum = "pending"
STATUS_REJECTED StatusEnum = "rejected"
STATUS_SENT StatusEnum = "sent"
STATUS_INVALID StatusEnum = "invalid"
)
func (s *StatusEnum) Scan(src interface{}) error {
if src == nil {
return errors.New("This field cannot be NULL")
}
if stringStatus, ok := src.([]byte); ok {
*s = StatusEnum(string(stringStatus[:]))
return nil
}
return errors.New("Cannot convert enum to string")
}
func (s *StatusEnum) Value() (driver.Value, error) {
return []byte(*s), nil
}
type EmailQueue struct {
Id uint64
Status StatusEnum
Body sql.NullString
}
func Save (db *sql.DB) error {
_, err = db.Exec(
"UPDATE `tableName` SET `Status` = ?, `Body` = ? WHERE `id` = ?",
&eqi.Status,
eqi.Body,
eqi.Id,
)
return err
}
więc moje pytanie to: Dlaczego muszę używać wskaźnika odniesienia (&eqi.Status
) na db.Exec
?
Zarówno sql.NullString
i mój zwyczaj StatusEnum
nie są realizowane w github.com/go-sql-driver/mysql
, więc dlaczego różnica?
Jeśli nie używam odniesienia wskaźnika (eqi.Status
), dostaję ten błąd (rzucanie w database/sql/convert.go):
sql: converting Exec argument #0's type: unsupported type emailqueue.StatusEnum, a string
starałem się wdrożyć kilka innych interfejsów mam ze nie znaleziono szczęście.
Mam inne typy niestandardowe zaimplementowane z interfejsami sql.Scanner
i sql.driver.Valuer
, ale problem jest taki sam.
Byłem zgadywania o struct
i różnicowanie typu dziedziczenia, ale nie mogłem dostać żadnego śladu na tym, że ... :(
Proszę pomóc zrozumieć, co się dzieje. Dzięki !!! :)
Naprawiono kod zastępujący '' 'EmailList'''' '' StatusEnum'''. Jest to jednak bardziej mylące, ponieważ ten kod działa doskonale: '' ', err: = eqi.Status.Value() \t v, err = (& eqi.Status) .Value()' '' –
Dla każdego, kto przyjdzie i czytanie, ponieważ można wywołać metodę wskaźnika na wartości innej niż wskaźnik i automatycznie pobierze adres, ale tylko wtedy, gdy jest to metoda bez interfejsu, tzn. zmienna jest interfejsem. https://golang.org/ref/spec#Method_values –