Skip to content

Commit ef59b9e

Browse files
committed
feat: ✨ add cobra command
add cobra command add cobra command
0 parents  commit ef59b9e

File tree

11 files changed

+419
-0
lines changed

11 files changed

+419
-0
lines changed

.github/workflows/go.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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
26+
run: task build

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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

README.md

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# golang-cobra-cli-sample
2+
3+
This repository is how to use cobra framework to write cli application
4+
5+
## dependency
6+
7+
1. cobra
8+
9+
```shell
10+
go get github.com/spf13/cobra@latest
11+
```
12+
13+
## logic
14+
15+
basic struct
16+
17+
main contain command.Execute method
18+
```golang
19+
package main
20+
21+
import (
22+
"log"
23+
24+
"github.com/leetcode-golang-classroom/golang-cobra-cli-sample/internal/command"
25+
)
26+
27+
func main() {
28+
err := command.Execute()
29+
if err != nil {
30+
log.Fatalf("command.Execute error: %v", err)
31+
}
32+
}
33+
34+
```
35+
36+
root cmd for handle main Execute
37+
```golang
38+
import "github.com/spf13/cobra"
39+
40+
var rootCmd = &cobra.Command{
41+
Use: "securerandom",
42+
Short: "Secure random number generators",
43+
Long: "an interface to secure random number generators",
44+
}
45+
46+
func Execute() error {
47+
return rootCmd.Execute()
48+
}
49+
50+
```
51+
hex.go for generate a random number with hex encoded
52+
```golang
53+
package command
54+
55+
import (
56+
"crypto/rand"
57+
"encoding/hex"
58+
"fmt"
59+
60+
"github.com/spf13/cobra"
61+
)
62+
63+
// hexCmd
64+
var hexCmd = &cobra.Command{
65+
Use: "hex",
66+
Short: "Generates Hex numbers",
67+
Long: `Provided length, it generates hex numbers.
68+
For example:
69+
securerandom hex -l 10`,
70+
Run: func(cmd *cobra.Command, args []string) {
71+
length, _ := cmd.Flags().GetInt("length")
72+
hex, err := generateHexString(length)
73+
if err != nil {
74+
fmt.Println(err)
75+
} else {
76+
fmt.Println(hex)
77+
}
78+
},
79+
}
80+
// init for add cmd, and flag setup
81+
func init() {
82+
rootCmd.AddCommand(hexCmd)
83+
hexCmd.Flags().IntP("length", "l", 4, "Length of hex")
84+
}
85+
86+
func generateHexString(length int) (string, error) {
87+
// Calculate the nubmer of bytes needed
88+
byteLength := (length + 1) / 2
89+
bytes := make([]byte, byteLength)
90+
// Generate random byte
91+
if _, err := rand.Read(bytes); err != nil {
92+
return "", err
93+
}
94+
// Conver to hex and truncate to the desired length
95+
hexString := hex.EncodeToString(bytes)[:length]
96+
return hexString, nil
97+
}
98+
99+
```
100+
101+
base64.go generate random number with base64 encoded
102+
```golang
103+
package command
104+
105+
import (
106+
"crypto/rand"
107+
"encoding/base64"
108+
"fmt"
109+
110+
"github.com/spf13/cobra"
111+
)
112+
113+
var base64Cmd = &cobra.Command{
114+
Use: "base64",
115+
Short: "Generate base64 string",
116+
Long: `Provided length, it generates base64 string.
117+
For example:
118+
securerandom base64 -l 10`,
119+
Run: func(cmd *cobra.Command, args []string) {
120+
length, _ := cmd.Flags().GetInt("length")
121+
str, err := generateBase64tring(length)
122+
if err != nil {
123+
fmt.Println(err)
124+
} else {
125+
fmt.Println(str)
126+
}
127+
},
128+
}
129+
130+
func generateBase64tring(byteLength int) (string, error) {
131+
// Generate random bytes
132+
bytes := make([]byte, byteLength)
133+
if _, err := rand.Read(bytes); err != nil {
134+
return "", err
135+
}
136+
// Encode the bytes ot a Base64 string
137+
base64String := base64.StdEncoding.EncodeToString(bytes)
138+
return base64String, nil
139+
}
140+
141+
func init() {
142+
rootCmd.AddCommand(base64Cmd)
143+
base64Cmd.Flags().IntP("length", "l", 4, "Length of base64")
144+
}
145+
146+
```
147+
148+
uuid.go for generate a uuid
149+
```golang
150+
package command
151+
152+
import (
153+
"fmt"
154+
155+
"github.com/google/uuid"
156+
"github.com/spf13/cobra"
157+
)
158+
159+
// uuidcmd represents the uuid command
160+
var uuidCmd = &cobra.Command{
161+
Use: "uuid",
162+
Short: "Generates UUID",
163+
Long: `Generates UUID. For example:
164+
165+
securerandom uuid`,
166+
Run: func(cmd *cobra.Command, args []string) {
167+
newUUID := uuid.New()
168+
fmt.Println(newUUID.String())
169+
},
170+
}
171+
172+
func init() {
173+
rootCmd.AddCommand(uuidCmd)
174+
}
175+
176+
```

Taskfile.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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/securerandom cmd/main.go
12+
silent: true
13+
run:
14+
cmds:
15+
- ./bin/main
16+
deps:
17+
- build
18+
silent: true
19+
coverage:
20+
cmds:
21+
- go test -v -cover ./...
22+
silent: true
23+
test:
24+
cmds:
25+
- go test -v ./...
26+
silent: true
27+

cmd/main.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package main
2+
3+
import (
4+
"log"
5+
6+
"github.com/leetcode-golang-classroom/golang-cobra-cli-sample/internal/command"
7+
)
8+
9+
func main() {
10+
err := command.Execute()
11+
if err != nil {
12+
log.Fatalf("command.Execute error: %v", err)
13+
}
14+
}

go.mod

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module github.com/leetcode-golang-classroom/golang-cobra-cli-sample
2+
3+
go 1.22.4
4+
5+
require (
6+
github.com/google/uuid v1.6.0
7+
github.com/spf13/cobra v1.8.1
8+
)
9+
10+
require (
11+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
12+
github.com/spf13/pflag v1.0.5 // indirect
13+
)

go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
2+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
3+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
4+
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
5+
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
6+
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
7+
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
8+
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
9+
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
10+
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
11+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
12+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/command/base64.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package command
2+
3+
import (
4+
"crypto/rand"
5+
"encoding/base64"
6+
"fmt"
7+
8+
"github.com/spf13/cobra"
9+
)
10+
11+
var base64Cmd = &cobra.Command{
12+
Use: "base64",
13+
Short: "Generate base64 string",
14+
Long: `Provided length, it generates base64 string.
15+
For example:
16+
securerandom base64 -l 10`,
17+
Run: func(cmd *cobra.Command, args []string) {
18+
length, _ := cmd.Flags().GetInt("length")
19+
str, err := generateBase64tring(length)
20+
if err != nil {
21+
fmt.Println(err)
22+
} else {
23+
fmt.Println(str)
24+
}
25+
},
26+
}
27+
28+
func generateBase64tring(byteLength int) (string, error) {
29+
// Generate random bytes
30+
bytes := make([]byte, byteLength)
31+
if _, err := rand.Read(bytes); err != nil {
32+
return "", err
33+
}
34+
// Encode the bytes ot a Base64 string
35+
base64String := base64.StdEncoding.EncodeToString(bytes)
36+
return base64String, nil
37+
}
38+
39+
func init() {
40+
rootCmd.AddCommand(base64Cmd)
41+
base64Cmd.Flags().IntP("length", "l", 4, "Length of base64")
42+
}

internal/command/hex.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package command
2+
3+
import (
4+
"crypto/rand"
5+
"encoding/hex"
6+
"fmt"
7+
8+
"github.com/spf13/cobra"
9+
)
10+
11+
// hexCmd
12+
var hexCmd = &cobra.Command{
13+
Use: "hex",
14+
Short: "Generates Hex numbers",
15+
Long: `Provided length, it generates hex numbers.
16+
For example:
17+
securerandom hex -l 10`,
18+
Run: func(cmd *cobra.Command, args []string) {
19+
length, _ := cmd.Flags().GetInt("length")
20+
hex, err := generateHexString(length)
21+
if err != nil {
22+
fmt.Println(err)
23+
} else {
24+
fmt.Println(hex)
25+
}
26+
},
27+
}
28+
29+
func init() {
30+
rootCmd.AddCommand(hexCmd)
31+
hexCmd.Flags().IntP("length", "l", 4, "Length of hex")
32+
}
33+
34+
func generateHexString(length int) (string, error) {
35+
// Calculate the nubmer of bytes needed
36+
byteLength := (length + 1) / 2
37+
bytes := make([]byte, byteLength)
38+
// Generate random byte
39+
if _, err := rand.Read(bytes); err != nil {
40+
return "", err
41+
}
42+
// Conver to hex and truncate to the desired length
43+
hexString := hex.EncodeToString(bytes)[:length]
44+
return hexString, nil
45+
}

0 commit comments

Comments
 (0)