Skip to content

Commit 92247d1

Browse files
committed
✨ add pgx sample with CRUD
0 parents  commit 92247d1

File tree

13 files changed

+704
-0
lines changed

13 files changed

+704
-0
lines changed

.github/workflows/go.yml

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Go
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
jobs:
11+
build_and_test:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Setup go-task
15+
uses: pnorton5432/setup-task@v1
16+
with:
17+
task-version: 3.29.1
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
- name: Setup Go
21+
uses: actions/setup-go@v5
22+
with:
23+
go-version: 'stable'
24+
check-latest: true
25+
- name: Task Build for mage
26+
run: task build-gg
27+
- name: Test with gg build
28+
run: ./gg build

.gitignore

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work
22+
go.work.sum
23+
24+
# env file
25+
.env
26+
bin
27+
gg
28+
mage
29+
dbdata

README.md

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
# golang-sample-with-pgx
2+
3+
This repository is to demo how to use pgx
4+
5+
## what is pgx?
6+
7+
pgx is a golang library for handle database connection handle function to PostgreSQL
8+
it provide extensive function more than the origin standard database pg library such as connection pool, data serialize
9+
10+
## why is pgx?
11+
12+
It could handle many basic stuff for handle database query and parameter sanitzation
13+
14+
## setup dependency
15+
16+
```shell
17+
go get github.com/jackc/pgx/v5
18+
```
19+
20+
## prepare schema
21+
22+
```sql
23+
CREATE TABLE IF NOT EXISTS authors (
24+
id SERIAL PRIMARY KEY,
25+
name TEXT NOT NULL,
26+
email TEXT UNIQUE NOT NULL
27+
);
28+
29+
CREATE TABLE IF NOT EXISTS books (
30+
id SERIAL PRIMARY KEY,
31+
title TEXT NOT NULL,
32+
author_id INTEGER REFERENCES authors(id),
33+
published_year INTEGER,
34+
genre TEXT
35+
);
36+
37+
CREATE TABLE IF NOT EXISTS members (
38+
id SERIAL PRIMARY KEY,
39+
name TEXT NOT NULL,
40+
email TEXT UNIQUE NOT NULL,
41+
join_date DATE NOT NULL DEFAULT CURRENT_DATE
42+
);
43+
```
44+
45+
## models
46+
47+
```golang
48+
package model
49+
50+
type Author struct {
51+
ID int32 `json:"id"`
52+
Name string `json:"name"`
53+
Email string `json:"email"`
54+
}
55+
56+
type Book struct {
57+
ID int32 `json:"id"`
58+
Title string `json:"title"`
59+
AuthorID int32 `json:"author_id"`
60+
PublishedYear int32 `json:"published_year"`
61+
Genre string `json:"genre"`
62+
}
63+
64+
type Member struct {
65+
ID int32 `json:"id"`
66+
Name string `json:"name"`
67+
Email string `json:"email"`
68+
JoinDate string `json:"join_date"`
69+
}
70+
```
71+
72+
## usage
73+
74+
### Connection Setup
75+
76+
```golang
77+
// Database connection with pool
78+
pool, err := pgxpool.New(context.Background(), config.AppConfig.DBURL)
79+
if err != nil {
80+
log.Fatalf("Unable to connect to database: %v", err)
81+
}
82+
defer pool.Close()
83+
```
84+
85+
### Transaction(Handle multiple data modification in one transaction)
86+
```golang
87+
// Transaction
88+
tx, err := pool.Begin(context.Background())
89+
if err != nil {
90+
log.Fatalf("Error starting transaction: %v", err)
91+
}
92+
defer tx.Rollback(context.Background())
93+
94+
_, err = tx.Exec(context.Background(), `
95+
INSERT INTO authors (name, email)
96+
VALUES ($1, $2);
97+
`, "George R.R. Martin", "george.martin@sample.io")
98+
if err != nil {
99+
log.Fatalf("Error inserting author: %v", err)
100+
}
101+
102+
_, err = tx.Exec(context.Background(), `
103+
INSERT INTO books (title, author_id, published_year, genre)
104+
VALUES ($1, $2, $3, $4);
105+
`, "Harry Potter", 1, 1997, "Fantasy")
106+
if err != nil {
107+
log.Fatalf("Error inserting book: %v", err)
108+
}
109+
110+
_, err = tx.Exec(context.Background(), `
111+
INSERT INTO members (name, email)
112+
VALUES ($1, $2);
113+
`, "John Doe", "john.doe@sample.com")
114+
if err != nil {
115+
log.Fatalf("Error inserting members: %v", err)
116+
}
117+
118+
err = tx.Commit(context.Background())
119+
if err != nil {
120+
log.Fatalf("Error committing transaction: %v", err)
121+
}
122+
```
123+
124+
### Query Authors (Query multiple record)
125+
```golang
126+
// Query All authors from database
127+
rows, err := pool.Query(context.Background(),
128+
`SELECT id, name, email FROM authors;`,
129+
)
130+
if err != nil {
131+
log.Fatalf("Error querying authors: %v", err)
132+
}
133+
defer rows.Close()
134+
135+
authors := make([]model.Author, 0, 100)
136+
for rows.Next() {
137+
var author model.Author
138+
if err := rows.Scan(&author.ID, &author.Name, &author.Email); err != nil {
139+
log.Fatalf("Error scanning row: %v", err)
140+
}
141+
authors = append(authors, author)
142+
}
143+
fmt.Println("Authors:", authors)
144+
```
145+
146+
### Query A Book (Single Record)
147+
```golang
148+
// Query single book from Database
149+
var book model.Book
150+
err = pool.QueryRow(context.Background(), `
151+
SELECT id, title, author_id, published_year, genre
152+
FROM books
153+
WHERE title=$1
154+
`, "Harry Potter").Scan(&book.ID, &book.Title, &book.AuthorID, &book.PublishedYear, &book.Genre)
155+
if err != nil {
156+
log.Fatalf("Error query book: %v", err)
157+
}
158+
fmt.Println("Book Detail:", book)
159+
```
160+
161+
### Update Author
162+
```golang
163+
// Update an author's name
164+
authorID := 1
165+
newName := "J.K. Rowling Updated"
166+
_, err = pool.Exec(context.Background(),
167+
`UPDATE authors SET name = $1
168+
WHERE id = $2
169+
`, newName, authorID,
170+
)
171+
if err != nil {
172+
log.Fatalf("Error updating author: %v", err)
173+
}
174+
fmt.Println("Author updated successfully")
175+
```
176+
177+
### DELETE Book
178+
```golang
179+
// DELETE a book by ID
180+
bookID := 1
181+
_, err = pool.Exec(context.Background(),
182+
`DELETE FROM books
183+
WHERE id = $1;
184+
`, bookID,
185+
)
186+
if err != nil {
187+
log.Fatalf("Error deleting book: %v", err)
188+
}
189+
fmt.Println("Book delete successfully")
190+
```

Taskfile.yml

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
version: '3'
2+
3+
dotenv: ['.env']
4+
5+
tasks:
6+
default:
7+
cmds:
8+
- echo "DB_URL=$DB_URL"
9+
silent: true
10+
11+
# build:
12+
# cmds:
13+
# - CGO_ENABLED=0 GOOS=linux go build -o bin/main cmd/main.go
14+
# silent: true
15+
# run:
16+
# cmds:
17+
# - ./bin/main
18+
# deps:
19+
# - build
20+
# silent: true
21+
22+
build-mage:
23+
cmds:
24+
- CGO_ENABLED=0 GOOS=linux go build -o ./mage mage-tools/mage.go
25+
silent: true
26+
27+
build-gg:
28+
cmds:
29+
- ./mage -d mage-tools -compile ../gg
30+
deps:
31+
- build-mage
32+
silent: true
33+
34+
coverage:
35+
cmds:
36+
- go test -v -cover ./...
37+
silent: true
38+
test:
39+
cmds:
40+
- go test -v ./...
41+
silent: true
42+

0 commit comments

Comments
 (0)