Skip to content

Commit 8b1b087

Browse files
committed
✨ add redis hashtable sample
0 parents  commit 8b1b087

File tree

18 files changed

+695
-0
lines changed

18 files changed

+695
-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+
mage
27+
gg
28+
bin
29+
data

Makefile

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.PHONY=build
2+
include .env
3+
export $(shell sed 's/=.*//' .env)
4+
build:
5+
@CGO_ENABLED=0 GOOS=linux go build -o bin/main cmd/main.go
6+
7+
run: build
8+
@./bin/main
9+
10+
11+
coverage:
12+
@go test -v -cover ./...
13+
14+
test:
15+
@go test -v ./...
16+
17+
redis-compose:
18+
@sudo docker compose up -d

README.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# golang-sample-with-redis
2+
3+
This repository for practice use redis with golang
4+
5+
## redis hashtable sample
6+
7+
```golang
8+
package main
9+
10+
import (
11+
"context"
12+
"fmt"
13+
"log/slog"
14+
"os"
15+
16+
"github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/config"
17+
"github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/logger"
18+
myredis "github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/redis"
19+
"github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/util"
20+
"github.com/redis/go-redis/v9"
21+
)
22+
23+
func main() {
24+
jsonLogger := slog.New(slog.NewJSONHandler(
25+
os.Stdout, &slog.HandlerOptions{
26+
AddSource: true,
27+
},
28+
))
29+
ctx := logger.CtxWithLogger(context.Background(), jsonLogger)
30+
config.Init(ctx)
31+
redisURL := config.AppCfg.RedisUrl
32+
rdb, err := myredis.New(redisURL)
33+
if err != nil {
34+
util.FailOnError(ctx, err, fmt.Sprintf("failed to connect to %s\n", redisURL))
35+
}
36+
defer rdb.Close()
37+
_, err = rdb.Ping(ctx)
38+
if err != nil {
39+
util.FailOnError(ctx, err, fmt.Sprintf("failed to ping to %s\n", redisURL))
40+
}
41+
// 建立 struct
42+
var rh1 = RedisHash{
43+
Name: "eddie",
44+
ID: 123,
45+
Online: true,
46+
}
47+
// 透過 pipeline 方式一次批量設定 hashtable
48+
rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {
49+
pipe.HSet(ctx, "rh1", "name", rh1.Name)
50+
pipe.HSet(ctx, "rh1", "id", rh1.ID)
51+
pipe.HSet(ctx, "rh1", "online", rh1.Online)
52+
return nil
53+
})
54+
var rh2 RedisHash
55+
// 採用 hash read 的方式一次讀取整個 hashtable 相關的 key 的整個結構
56+
err = rdb.HGetAll(ctx, "rh1").Scan(&rh2)
57+
if err != nil {
58+
util.FailOnError(ctx, err, "failed on scan rh2")
59+
}
60+
jsonLogger.Info("hash sample", slog.Any("rh2", rh2))
61+
}
62+
63+
// RedisHash struct for handle
64+
type RedisHash struct {
65+
Name string `redis:"name"`
66+
ID int32 `redis:"id"`
67+
Online bool `redis:"online"`
68+
}
69+
70+
```

Taskfile.yml

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

cmd/basic-sample/main.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log/slog"
7+
"os"
8+
9+
"github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/config"
10+
"github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/logger"
11+
myredis "github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/redis"
12+
"github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/util"
13+
"github.com/redis/go-redis/v9"
14+
)
15+
16+
func main() {
17+
jsonLogger := slog.New(slog.NewJSONHandler(
18+
os.Stdout, &slog.HandlerOptions{
19+
AddSource: true,
20+
},
21+
))
22+
ctx := logger.CtxWithLogger(context.Background(), jsonLogger)
23+
config.Init(ctx)
24+
redisURL := config.AppCfg.RedisUrl
25+
rdb, err := myredis.New(redisURL)
26+
if err != nil {
27+
util.FailOnError(ctx, err, fmt.Sprintf("failed to connect to %s\n", redisURL))
28+
}
29+
defer rdb.Close()
30+
_, err = rdb.Ping(ctx)
31+
if err != nil {
32+
util.FailOnError(ctx, err, fmt.Sprintf("failed to ping to %s\n", redisURL))
33+
}
34+
err = rdb.Set(ctx, "key1", "value1", 0)
35+
if err != nil {
36+
util.FailOnError(ctx, err, "failed to set key1")
37+
}
38+
res, err := rdb.Get(ctx, "key1")
39+
if err != nil {
40+
jsonLogger.Error("failed to get key1")
41+
} else {
42+
jsonLogger.Info("result get", slog.Any("res", res))
43+
}
44+
_, err = rdb.Get(ctx, "key2")
45+
if err != nil {
46+
if err == redis.Nil {
47+
jsonLogger.Error("key2 does not exists")
48+
} else {
49+
jsonLogger.Error("err", slog.Any("err", err))
50+
}
51+
}
52+
}

cmd/hash-sample/main.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log/slog"
7+
"os"
8+
9+
"github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/config"
10+
"github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/logger"
11+
myredis "github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/redis"
12+
"github.com/leetcode-golang-classroom/golang-sample-with-redis/internal/util"
13+
"github.com/redis/go-redis/v9"
14+
)
15+
16+
func main() {
17+
jsonLogger := slog.New(slog.NewJSONHandler(
18+
os.Stdout, &slog.HandlerOptions{
19+
AddSource: true,
20+
},
21+
))
22+
ctx := logger.CtxWithLogger(context.Background(), jsonLogger)
23+
config.Init(ctx)
24+
redisURL := config.AppCfg.RedisUrl
25+
rdb, err := myredis.New(redisURL)
26+
if err != nil {
27+
util.FailOnError(ctx, err, fmt.Sprintf("failed to connect to %s\n", redisURL))
28+
}
29+
defer rdb.Close()
30+
_, err = rdb.Ping(ctx)
31+
if err != nil {
32+
util.FailOnError(ctx, err, fmt.Sprintf("failed to ping to %s\n", redisURL))
33+
}
34+
var rh1 = RedisHash{
35+
Name: "eddie",
36+
ID: 123,
37+
Online: true,
38+
}
39+
rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {
40+
pipe.HSet(ctx, "rh1", "name", rh1.Name)
41+
pipe.HSet(ctx, "rh1", "id", rh1.ID)
42+
pipe.HSet(ctx, "rh1", "online", rh1.Online)
43+
return nil
44+
})
45+
var rh2 RedisHash
46+
err = rdb.HGetAll(ctx, "rh1").Scan(&rh2)
47+
if err != nil {
48+
util.FailOnError(ctx, err, "failed on scan rh2")
49+
}
50+
jsonLogger.Info("hash sample", slog.Any("rh2", rh2))
51+
}
52+
53+
// RedisHash struct for handle
54+
type RedisHash struct {
55+
Name string `redis:"name"`
56+
ID int32 `redis:"id"`
57+
Online bool `redis:"online"`
58+
}

docker-compose.yml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
services:
2+
redis:
3+
build:
4+
context: .
5+
dockerfile: ./redis-dockerfile
6+
container_name: sample-redis
7+
restart: always
8+
ports:
9+
- ${REDIS_PORT}:6379
10+
volumes:
11+
- ./data:/data
12+
environment:
13+
- REDIS_PASSWORD=${REDIS_PASSWORD}
14+
- REDIS_PORT=${REDIS_PORT}
15+
16+
networks:
17+
sample-redis:
18+
driver: bridge

go.mod

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module github.com/leetcode-golang-classroom/golang-sample-with-redis
2+
3+
go 1.24.0
4+
5+
require (
6+
github.com/magefile/mage v1.15.0
7+
github.com/redis/go-redis/v9 v9.7.3
8+
github.com/spf13/viper v1.20.1
9+
)
10+
11+
require (
12+
github.com/cespare/xxhash/v2 v2.3.0 // indirect
13+
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
14+
github.com/fsnotify/fsnotify v1.8.0 // indirect
15+
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
16+
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
17+
github.com/sagikazarmark/locafero v0.7.0 // indirect
18+
github.com/sourcegraph/conc v0.3.0 // indirect
19+
github.com/spf13/afero v1.12.0 // indirect
20+
github.com/spf13/cast v1.7.1 // indirect
21+
github.com/spf13/pflag v1.0.6 // indirect
22+
github.com/subosito/gotenv v1.6.0 // indirect
23+
go.uber.org/atomic v1.9.0 // indirect
24+
go.uber.org/multierr v1.9.0 // indirect
25+
golang.org/x/sys v0.29.0 // indirect
26+
golang.org/x/text v0.21.0 // indirect
27+
gopkg.in/yaml.v3 v3.0.1 // indirect
28+
)

0 commit comments

Comments
 (0)