diff options
Diffstat (limited to 'test/typeparam/issue47896.go')
-rw-r--r-- | test/typeparam/issue47896.go | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/test/typeparam/issue47896.go b/test/typeparam/issue47896.go new file mode 100644 index 0000000..616e907 --- /dev/null +++ b/test/typeparam/issue47896.go @@ -0,0 +1,74 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "database/sql" +) + +// Collection generic interface which things can be added to. +type Collection[T any] interface { + Add(T) +} + +// Slice generic slice implementation of a Collection +type Slice[T any] []*T + +func (s *Slice[T]) Add(t *T) { + *s = append(*s, t) +} + +type Scanner interface { + Scan(...interface{}) error +} + +type Mapper[T any] func(s Scanner, t T) error + +type Repository[T any] struct { + db *sql.DB +} + +func (r *Repository[T]) scan(rows *sql.Rows, m Mapper[*T], c Collection[*T]) error { + for rows.Next() { + t := new(T) + if err := m(rows, t); err != nil { + return err + } + c.Add(t) + } + return rows.Err() +} + +func (r *Repository[T]) query(query string, m Mapper[*T], c Collection[*T]) error { + rows, err := r.db.Query(query) + if err != nil { + return err + } + if err := r.scan(rows, m, c); err != nil { + rows.Close() + return err + } + return rows.Close() +} + +type Actor struct { + ActorID uint16 + FirstName string + LastName string +} + +type ActorRepository struct { + r Repository[Actor] +} + +func (ActorRepository) scan(s Scanner, a *Actor) error { + return s.Scan(&a.ActorID, &a.FirstName, &a.LastName) +} + +func (r *ActorRepository) SelectAll(c Collection[*Actor]) error { + return r.r.query("SELECT `actor_id`, `first_name`, `last_name` FROM `actor` LIMIT 10", r.scan, c) +} |