Skip to content

Commit 1395a20

Browse files
committed
feat: add new samples
1 parent 241a098 commit 1395a20

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+4769
-0
lines changed

mixapi/.env

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# APP
2+
APP_DEBUG=true
3+
4+
# DATABASE
5+
DATABASE_DSN=root:123456@tcp(127.0.0.1:3306)/test?charset=utf8&loc=Asia%2FShanghai&parseTime=true&timeout=10s
6+
7+
# REDIS
8+
REDIS_ADDR=127.0.0.1:6379
9+
REDIS_DATABASE=0
10+
REDIS_PASSWORD=
11+
REDIS_DIAL_TIMEOUT=10
12+
13+
# GIN
14+
GIN_ADDR=:8080
15+
GIN_MODE=test
16+
17+
# JWT
18+
HMAC_SECRET=my_secret_key

mixapi/.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# goland project files
2+
.idea
3+
4+
# netbeans project files
5+
nbproject
6+
7+
# zend studio for eclipse project files
8+
.buildpath
9+
.project
10+
.settings
11+
12+
# windows thumbnail cache
13+
Thumbs.db
14+
15+
# Mac DS_Store Files
16+
.DS_Store

mixapi/README.md

Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
## API development skeleton
2+
3+
帮助你快速搭建项目骨架,并指导你如何使用该骨架的细节。
4+
5+
## Installation
6+
7+
- Install
8+
9+
~~~
10+
go install -u github.com/mix-go/mixcli
11+
~~~
12+
13+
- New project
14+
15+
~~~
16+
mixcli new hello
17+
~~~
18+
19+
~~~
20+
Use the arrow keys to navigate: ↓ ↑ → ←
21+
? Select project type:
22+
CLI
23+
▸ API
24+
Web (contains the websocket)
25+
gRPC
26+
~~~
27+
28+
## 编写一个 API 服务
29+
30+
首先我们使用 `mixcli` 命令创建一个项目骨架:
31+
32+
~~~
33+
$ mixcli new hello
34+
~~~
35+
36+
生成骨架目录结构如下:
37+
38+
~~~
39+
.
40+
├── README.md
41+
├── bin
42+
├── commands
43+
├── conf
44+
├── config
45+
├── controllers
46+
├── di
47+
├── go.mod
48+
├── go.sum
49+
├── main.go
50+
├── middleware
51+
├── routes
52+
└── runtime
53+
~~~
54+
55+
`main.go` 文件:
56+
57+
- `xcli.AddCommand` 方法传入的 `commands.Commands` 定义了全部的命令
58+
59+
~~~go
60+
package main
61+
62+
import (
63+
"mixapi/commands"
64+
_ "mixapi/configor"
65+
_ "mixapi/di"
66+
_ "mixapi/dotenv"
67+
"github.com/mix-go/xutil/xenv"
68+
"github.com/mix-go/xcli"
69+
)
70+
71+
func main() {
72+
xcli.SetName("app").
73+
SetVersion("0.0.0-alpha").
74+
SetDebug(xenv.Getenv("APP_DEBUG").Bool(false))
75+
xcli.AddCommand(commands.Commands...).Run()
76+
}
77+
~~~
78+
79+
`commands/main.go` 文件:
80+
81+
我们可以在这里自定义命令,[查看更多](https://github.com/mix-go/xcli)
82+
83+
- `RunI` 指定了命令执行的接口,也可以使用 `RunF` 设定一个匿名函数
84+
85+
```go
86+
package commands
87+
88+
import (
89+
"github.com/mix-go/xcli"
90+
)
91+
92+
var Commands = []*xcli.Command{
93+
{
94+
Name: "api",
95+
Short: "\tStart the api server",
96+
Options: []*xcli.Option{
97+
{
98+
Names: []string{"a", "addr"},
99+
Usage: "\tListen to the specified address",
100+
},
101+
{
102+
Names: []string{"d", "daemon"},
103+
Usage: "\tRun in the background",
104+
},
105+
},
106+
RunI: &APICommand{},
107+
},
108+
}
109+
```
110+
111+
`commands/api.go` 文件:
112+
113+
业务代码写在 `APICommand` 结构体的 `main` 方法中,生成的代码中已经包含了:
114+
115+
- 监听信号停止服务
116+
- 根据模式打印日志
117+
- 可选的后台守护执行
118+
119+
基本上无需修改即可上线使用
120+
121+
~~~go
122+
package commands
123+
124+
import (
125+
"context"
126+
"fmt"
127+
"github.com/gin-gonic/gin"
128+
"mixapi/di"
129+
"mixapi/routes"
130+
"github.com/mix-go/xutil/xenv"
131+
"github.com/mix-go/xcli/flag"
132+
"github.com/mix-go/xcli/process"
133+
"os"
134+
"os/signal"
135+
"strings"
136+
"syscall"
137+
"time"
138+
)
139+
140+
type APICommand struct {
141+
}
142+
143+
func (t *APICommand) Main() {
144+
if flag.Match("d", "daemon").Bool() {
145+
process.Daemon()
146+
}
147+
148+
logger := di.Zap()
149+
server := di.Server()
150+
addr := xenv.Getenv("GIN_ADDR").String(":8080")
151+
mode := xenv.Getenv("GIN_MODE").String(gin.ReleaseMode)
152+
153+
// server
154+
gin.SetMode(mode)
155+
router := gin.New()
156+
routes.SetRoutes(router)
157+
server.Addr = flag.Match("a", "addr").String(addr)
158+
server.Handler = router
159+
160+
// signal
161+
ch := make(chan os.Signal)
162+
signal.Notify(ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
163+
go func() {
164+
<-ch
165+
logger.Info("Server shutdown")
166+
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
167+
if err := server.Shutdown(ctx); err != nil {
168+
logger.Errorf("Server shutdown error: %s", err)
169+
}
170+
}()
171+
172+
// logger
173+
if mode != gin.ReleaseMode {
174+
handlerFunc := gin.LoggerWithConfig(gin.LoggerConfig{
175+
Formatter: func(params gin.LogFormatterParams) string {
176+
return fmt.Sprintf("%s|%s|%d|%s",
177+
params.Method,
178+
params.Path,
179+
params.StatusCode,
180+
params.ClientIP,
181+
)
182+
},
183+
Output: logger.Out,
184+
})
185+
router.Use(handlerFunc)
186+
}
187+
188+
// run
189+
welcome()
190+
logger.Infof("Server start at %s", server.Addr)
191+
if err := server.ListenAndServe(); err != nil && !strings.Contains(err.Error(), "http: Server closed") {
192+
panic(err)
193+
}
194+
}
195+
~~~
196+
197+
`routes/main.go` 文件中配置路由:
198+
199+
已经包含一些常用实例,只需要在这里新增路由即可开始开发
200+
201+
~~~go
202+
package routes
203+
204+
import (
205+
"github.com/gin-gonic/gin"
206+
"mixapi/controllers"
207+
"mixapi/middleware"
208+
)
209+
210+
func SetRoutes(router *gin.Engine) {
211+
router.Use(gin.Recovery()) // error handle
212+
213+
router.GET("hello",
214+
middleware.CorsMiddleware(),
215+
func(ctx *gin.Context) {
216+
hello := controllers.HelloController{}
217+
hello.Index(ctx)
218+
},
219+
)
220+
221+
router.POST("users/add",
222+
middleware.AuthMiddleware(),
223+
func(ctx *gin.Context) {
224+
hello := controllers.UserController{}
225+
hello.Add(ctx)
226+
},
227+
)
228+
229+
router.POST("auth", func(ctx *gin.Context) {
230+
auth := controllers.AuthController{}
231+
auth.Index(ctx)
232+
})
233+
}
234+
~~~
235+
236+
接下来我们编译上面的程序:
237+
238+
- linux & macOS
239+
240+
~~~
241+
go build -o bin/go_build_main_go main.go
242+
~~~
243+
244+
- win
245+
246+
~~~
247+
go build -o bin/go_build_main_go.exe main.go
248+
~~~
249+
250+
启动服务器
251+
252+
~~~
253+
$ bin/go_build_main_go api
254+
___
255+
______ ___ _ /__ ___ _____ ______
256+
/ __ `__ \/ /\ \/ /__ __ `/ __ \
257+
/ / / / / / / /\ \/ _ /_/ // /_/ /
258+
/_/ /_/ /_/_/ /_/\_\ \__, / \____/
259+
/____/
260+
261+
262+
Server Name: mix-api
263+
System Name: darwin
264+
Go Version: 1.13.4
265+
Listen Addr: :8080
266+
time=2020-09-16 20:24:41.515 level=info msg=Server start file=api.go:58
267+
~~~
268+
269+
## 如何使用 DI 容器中的 Logger、Database、Redis 等组件
270+
271+
项目中要使用的公共组件,都定义在 `di` 目录,框架默认生成了一些常用的组件,用户也可以定义自己的组件,[查看更多](https://github.com/mix-go/xdi)
272+
273+
- 可以在哪里使用
274+
275+
可以在代码的任意位置使用,但是为了可以使用到环境变量和自定义配置,通常我们在 `xcli.Command` 结构体定义的 `RunF``RunI` 中使用。
276+
277+
- 使用日志,比如:[zap](https://github.com/uber-go/zap)[logrus](https://github.com/Sirupsen/logrus)
278+
279+
```go
280+
logger := di.Zap()
281+
logger.Info("test")
282+
```
283+
284+
- 使用数据库,比如:[gorm](https://gorm.io/)[xorm](https://xorm.io/)
285+
286+
```go
287+
db := di.Gorm()
288+
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
289+
result := db.Create(&user)
290+
fmt.Println(result)
291+
```
292+
293+
- 使用 Redis,比如:[go-redis](https://redis.uptrace.dev/)
294+
295+
```go
296+
rdb := di.GoRedis()
297+
val, err := rdb.Get(context.Background(), "key").Result()
298+
if err != nil {
299+
panic(err)
300+
}
301+
fmt.Println("key", val)
302+
```
303+
304+
## 部署
305+
306+
线上部署时,不需要部署源码到服务器,只需要部署编译好的二进制、配置文件等
307+
308+
```
309+
├── bin
310+
├── conf
311+
├── runtime
312+
├── shell
313+
└── .env
314+
```
315+
316+
修改 `shell/server.sh` 脚本中的绝对路径和参数
317+
318+
```
319+
file=/project/bin/program
320+
cmd=api
321+
```
322+
323+
启动管理
324+
325+
```
326+
sh shell/server.sh start
327+
sh shell/server.sh stop
328+
sh shell/server.sh restart
329+
```
330+
331+
使用 `nginx` 或者 `SLB` 代理到服务器端口即可
332+
333+
```
334+
server {
335+
server_name www.domain.com;
336+
listen 80;
337+
338+
location / {
339+
proxy_http_version 1.1;
340+
proxy_set_header Connection "keep-alive";
341+
proxy_set_header Host $http_host;
342+
proxy_set_header Scheme $scheme;
343+
proxy_set_header X-Real-IP $remote_addr;
344+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
345+
if (!-f $request_filename) {
346+
proxy_pass http://127.0.0.1:8080;
347+
}
348+
}
349+
}
350+
```
351+
352+
## License
353+
354+
Apache License Version 2.0, http://www.apache.org/licenses/

mixapi/bin/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

0 commit comments

Comments
 (0)