Cookies management by TermsFeed Cookie Consent

Complete the demo procedure

16/21

We already have a working application using the repository implementation and calling the demo procedure. However, it would be good for the demo procedure to do more than just migrate data. So complete the app/demo.go file, and let’s trace what the newly added operations do.

  1. MIGRATE REPOSITORY - As you already know, at the beginning, we executed the Migrate() function, which created the websites database table.
  2. CREATE RECORDS OF REPOSITORY - Next, in lines 18 to 43, we create 2 new Website objects and add them to the repository using the Create() method. Then we print out the inserted records to the standard output. Note how we handle errors from the Create() method. In the case of an ErrDuplicate error, we only log that fact; in the case of a non-standard, unexpected error, we abort the application execution by logging the error using the log.Fatal() function.
  3. GET RECORD BY NAME - After inserting the records to the database, we check if we can pull them from there. In lines 45-53, we get a record named GOSAMPLES using the GetByName() method. If such a row does not exist, we log an ErrNotExist error and move on. Other unknown errors are logged, and the application exits.
  4. UPDATE RECORD - In lines 55-65, we update a single record with a new ranking value. Because the Update() method may return ErrDuplicate or ErrUpdateFailed errors, we check for them and handle them by printing on the standard output.
  5. GET ALL - Lines 67 through 75 use the All() method to get a list of all records and then print them to the standard output, so we can check that the update actually was made in the database.
  6. DELETE RECORD - In lines 77-84, we delete one of the inserted records and handle errors if they occur. In the case of ErrDeleteFailed, we log the error; in the case of others, we exit the application.
  7. GET ALL - As the last thing, in lines 86-93, we again get the list of all records using the All() method and write them out to the standard output to check if the row was actually deleted.

Now you can run our cmd/classic/main.go application using

go run main.go

and check the output:

1. MIGRATE REPOSITORY
2. CREATE RECORDS OF REPOSITORY
&{ID:1 Name:GOSAMPLES URL:https://gosamples.dev Rank:2}
&{ID:2 Name:Golang official website URL:https://golang.org Rank:1}
3. GET RECORD BY NAME
&{ID:1 Name:GOSAMPLES URL:https://gosamples.dev Rank:2}
4. UPDATE RECORD
5. GET ALL
{ID:2 Name:Golang official website URL:https://golang.org Rank:1}
{ID:1 Name:GOSAMPLES URL:https://gosamples.dev Rank:1}
6. DELETE RECORD
7. GET ALL
{ID:1 Name:GOSAMPLES URL:https://gosamples.dev Rank:1}

Feel free to experiment on your own. If this is your first application connecting to PostgreSQL, change function input arguments, change data, run the application multiple times and see what happens, check what errors appear, and try to fix them. The code we have created is just an introduction, which you should use as a base to create something more advanced.

Remember that when you run the application for the second time, you have already inserted data into the websites table. If you want to clean the database, just close the running PostgreSQL Docker container and restart it using docker run as in the beginning.


This way, we finished building the application that performs CRUD operations using the repository based on the database/sql package. In the following pages, we will show you how to create a repository based on the pgx client package, and using an ORM called GORM.

app/demo.go

 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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package app

import (
    "context"
    "errors"
    "fmt"
    "log"
    "postgresql-intro/website"
)

func RunRepositoryDemo(ctx context.Context, websiteRepository website.Repository) {
    fmt.Println("1. MIGRATE REPOSITORY")

    if err := websiteRepository.Migrate(ctx); err != nil {
        log.Fatal(err)
    }

    fmt.Println("2. CREATE RECORDS OF REPOSITORY")
    gosamples := website.Website{
        Name: "GOSAMPLES",
        URL:  "https://gosamples.dev",
        Rank: 2,
    }
    golang := website.Website{
        Name: "Golang official website",
        URL:  "https://golang.org",
        Rank: 1,
    }

    createdGosamples, err := websiteRepository.Create(ctx, gosamples)
    if errors.Is(err, website.ErrDuplicate) {
        fmt.Printf("record: %+v already exists\n", gosamples)
    } else if err != nil {
        log.Fatal(err)
    }
    createdGolang, err := websiteRepository.Create(ctx, golang)
    if errors.Is(err, website.ErrDuplicate) {
        log.Printf("record: %+v already exists\n", golang)
    } else if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%+v\n%+v\n", createdGosamples, createdGolang)

    fmt.Println("3. GET RECORD BY NAME")
    gotGosamples, err := websiteRepository.GetByName(ctx, "GOSAMPLES")
    if errors.Is(err, website.ErrNotExist) {
        log.Println("record: GOSAMPLES does not exist in the repository")
    } else if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%+v\n", gotGosamples)

    fmt.Println("4. UPDATE RECORD")
    createdGosamples.Rank = 1
    if _, err := websiteRepository.Update(ctx, createdGosamples.ID, *createdGosamples); err != nil {
        if errors.Is(err, website.ErrDuplicate) {
            fmt.Printf("record: %+v already exists\n", createdGosamples)
        } else if errors.Is(err, website.ErrUpdateFailed) {
            fmt.Printf("update of record: %+v failed", createdGolang)
        } else {
            log.Fatal(err)
        }
    }

    fmt.Println("5. GET ALL")
    all, err := websiteRepository.All(ctx)
    if err != nil {
        log.Fatal(err)
    }

    for _, website := range all {
        fmt.Printf("%+v\n", website)
    }

    fmt.Println("6. DELETE RECORD")
    if err := websiteRepository.Delete(ctx, createdGolang.ID); err != nil {
        if errors.Is(err, website.ErrDeleteFailed) {
            fmt.Printf("delete of record: %d failed", createdGolang.ID)
        } else {
            log.Fatal(err)
        }
    }

    fmt.Println("7. GET ALL")
    all, err = websiteRepository.All(ctx)
    if err != nil {
        log.Fatal(err)
    }
    for _, website := range all {
        fmt.Printf("%+v\n", website)
    }
}
16/21