aboutsummaryrefslogtreecommitdiff
path: root/test/typeparam/issue47896.go
blob: 1b2f265cc112123a5c3f210bc3ec24350d9b6b87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//  compile -G=3

// 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)
}