Heim  >  Artikel  >  Backend-Entwicklung  >  Wie füge ich eine Schnittstelle zu einer nicht-nativen Struktur in Golang hinzu?

Wie füge ich eine Schnittstelle zu einer nicht-nativen Struktur in Golang hinzu?

王林
王林nach vorne
2024-02-06 08:18:111033Durchsuche

Wie füge ich eine Schnittstelle zu einer nicht-nativen Struktur in Golang hinzu?

Frageninhalt

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 bringen
type 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

angebe
func (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?


Richtige Antwort


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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen