Ich verwende https://github.com/lib/pq, um Daten von Postgres abzurufen. Um die Daten zu extrahieren, verwende ich eine Drittanbieterstruktur, die das Protobuf-Zeitstempelfeld https://pkg.go.dev/google.golang.org/protobuf/types/known/timestamppb#timestamp enthält Also Das Problem besteht also darin, den Job zum Scannen von time.time nach timestamppb.timestamp
zu bringentype stuff struct { //this struct non-local, this is from third-party package date *timestamppb.timestamp } stuff = stuff{} scanerr := rows.scan(&stuff.date)
Ich versuche, die Struktur zu scannen, die die sql.scanner-Schnittstelle implementiert. Das ist einfach. Ich habe die Scan-Funktion gerade so implementiert:
type test struct { } func (t test) scan(src any) error { //convert value }
Aber es funktioniert nicht mit timestamppb.timestamp, da es sich um einen nicht nativen Typ handelt. Dann habe ich versucht, einen lokalen Typ zu definieren und dasselbe zu tun
type timestamppb timestamppb.timestamp func (t timestamppb) scan(src any) error { //convert value }
Aber dieser Trick hat nicht funktioniert. Außerdem erhalte ich die Warnung „‚Scan‘ übergibt die Sperre nach Wert: Typ ‚timestamppb‘ enthält ‚protoimpl.messagestate‘ enthält ‚sync.mutex‘, d. h. ‚sync.locker‘“ Dies funktioniert nicht, wenn ich einen Zeiger für timestampppb
angebefunc (t *timestamppb) scan(src any) error {
Ich möchte also wissen, wie man eine timestamppb.timestamp-Instanz von sql.scanner erstellt. Ist es möglich?
Update 1 Kleines Beispiel von dem, was ich versucht habe
type TimestampPb timestamppb.Timestamp type test struct { //third-party struct, I can't modify it date *timestamppb.Timestamp } func (s *Storage) test() { rows, _ := s.db.Query("SELECT \"test_date\" FROM \"test_table\" LIMIT 1") defer func() { if rows != nil { _ = rows.Close() } }() for rows.Next() { //var value *TimestampPb //works //var value TimestampPb //works //var value *timestamppb.Timestamp //doesn't work //testStruct := test{} //doesn't work //err := rows.Scan(&value) //scan to variable //err := rows.Scan(&testStruct.date) //scan to field in the struct if err != nil { log.Fatalln(err) } } } func (tpb *TimestampPb) Scan(src any) error { return nil }
Ich möchte wissen, ob ich case mit teststruct verwenden kann?
pq
库不支持 *timestamppb.timestamp
als Zeitstempeltyp. Informationen zu den unterstützten Datumstypen finden Sie in der Dokumentation.
Beim Scannen sind verschiedene Typen erforderlich.
Normalerweise verwende ich dazu Hilfstypen in Funktionen. Zum Beispiel:
type row struct { Date *timestamppb.Timestamp // ... more fields here } func Query() ([]row, error) { rows, err := s.db.Query(...) if err != nil { return nil, err } defer rows.Close() var rows []row for rows.Next() { type aux struct { Date time.Time // ... more fields here } var value aux if err := rows.Scan(&value); err != nil { return nil, err } rows = append(rows, row{ Date: timestamppb.New(value.Date), // ... more fields here } } return rows, nil }
Das obige ist der detaillierte Inhalt vonWie füge ich eine Schnittstelle zu einer nicht-nativen Struktur in Golang hinzu?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!