Maison >développement back-end >Golang >Comment ajouter une interface à une structure non native dans Golang ?

Comment ajouter une interface à une structure non native dans Golang ?

王林
王林avant
2024-02-06 08:18:111119parcourir

Comment ajouter une interface à une structure non native dans Golang ?

Contenu de la question

J'utilise https://github.com/lib/pq pour obtenir des données de postgres. Pour extraire les données, j'utilise une structure tierce qui contient le champ d'horodatage protobuf https://pkg.go.dev/google.golang.org/protobuf/types/known/timestampb#timestamp donc Le problème est donc de faire en sorte que le travail soit analysé de time.time à timestampb.timestamp

type stuff struct { //this struct non-local, this is from third-party package
  date *timestamppb.timestamp
}

stuff = stuff{}

scanerr := rows.scan(&stuff.date)

J'essaie de scanner la structure implémentant l'interface sql.scanner. C'est simple. Je viens d'implémenter la fonction scan comme ceci :

type test struct {
}


func (t test) scan(src any) error {
//convert value
}

Mais cela ne fonctionne pas avec timestamppb.timestamp car c'est un type non natif. Ensuite, j'ai essayé de définir un type local et de faire de même

type timestamppb timestamppb.timestamp

func (t timestamppb) scan(src any) error {
//convert value
}

Mais cette astuce n’a pas fonctionné. De plus, j'ai l'avertissement "'scan' passe le verrouillage par valeur : type 'timestamppb' contient 'protoimpl.messagestate' contient 'sync.mutex', c'est-à-dire 'sync.locker'" Cela ne fonctionne pas si je spécifie un pointeur pour timestampb

func (t *timestamppb) scan(src any) error {

Je veux donc savoir comment créer une instance timestamppb.timestamp de sql.scanner. Est-il possible?

Mise à jour 1 Petit exemple de ce que j'ai essayé

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
}

Je veux savoir si je peux utiliser case avec teststruct ?


Réponse correcte


pq 库不支持 *timestamppb.timestamp comme type d'horodatage. Voir la documentation pour les types de dates pris en charge.

Différents types sont requis lors de la numérisation.

Je fais généralement cela en utilisant des types d'assistance dans les fonctions. Par exemple :

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
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer