自定义 HTTP 配置
直接使用 http.ListenAndServe()
:
1 2 3 4
| func main() { router := gin.Default() http.ListenAndServe(":8080", router) }
|
或者首先定义 http.Server
,再调用 http.Server.ListenAndServe()
:
1 2 3 4 5 6 7 8 9 10 11 12
| func main() { router := gin.Default()
s := &http.Server{ Addr: ":8080", Handler: router, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } s.ListenAndServe() }
|
运行多个服务
errgroup 库
在 Go 语言中,我们可以使用 errgroup
库处理 goroutine
中的错误。
基本使用
使用 errgroup
库的 Go()
方法启动两个 goroutine
,分别模拟错误 goroutine
和正常 goroutine
。
然后,使用 errgroup
库的 Wait()
方法判断是否有 goroutine
返回错误信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| func main() { eg := errgroup.Group{} eg.Go(func() error { fmt.Println("go1") return nil }) eg.Go(func() error { fmt.Println("go2") err := errors.New("go2 err") return err }) err := eg.Wait() if err != nil { fmt.Println("err =", err) } }
|
附加 cancel 功能
使用 errgroup
库的 WithContext()
函数,可以附加 cancel
功能。
在第一个使用 Go()
方法启动的协程函数中,使用 select ... case ... default
监听其他协程是否返回错误并做出相应的逻辑处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| func main() { eg, ctx := errgroup.WithContext(context.Background()) eg.Go(func() error { time.Sleep(1 * time.Second) select { case <-ctx.Done(): fmt.Println("go1 cancel, err = ", ctx.Err()) default: fmt.Println("go1 run") } return nil }) eg.Go(func() error { err := errors.New("go2 err") return err }) err := eg.Wait() if err != nil { fmt.Println("err =", err) } }
|
限制并发数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| func main() { eg := errgroup.Group{} eg.SetLimit(2) eg.TryGo(func() error { fmt.Println("go1 run") return nil }) eg.TryGo(func() error { err := errors.New("go2 err") return err }) eg.TryGo(func() error { fmt.Println("go3 run") return nil }) err := eg.Wait() if err != nil { fmt.Println("err =", err) } }
|
利用 errgroup 运行多个服务
可以利用 errgroup 库运行多个服务,具体的方法是:
- 定义多个 http.Server,每一个 http.Server 都运行一个服务。
- 利用 errgroup.Go 函数运行每一个服务,即在每一个 errgroup.Go 内部都调用 ListenAndServe。
- 使用 errgroup 库的 Wait 方法判断是否有服务返回错误信息。
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
| package main
import ( "log" "net/http" "time"
"github.com/gin-gonic/gin" "golang.org/x/sync/errgroup" )
var ( g errgroup.Group )
func router01() http.Handler { e := gin.New() e.Use(gin.Recovery()) e.GET("/", func(c *gin.Context) { c.JSON( http.StatusOK, gin.H{ "code": http.StatusOK, "error": "Welcome server 01", }, ) })
return e }
func router02() http.Handler { e := gin.New() e.Use(gin.Recovery()) e.GET("/", func(c *gin.Context) { c.JSON( http.StatusOK, gin.H{ "code": http.StatusOK, "error": "Welcome server 02", }, ) })
return e }
func main() { server01 := &http.Server{ Addr: ":8080", Handler: router01(), ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, }
server02 := &http.Server{ Addr: ":8081", Handler: router02(), ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, }
g.Go(func() error { return server01.ListenAndServe() })
g.Go(func() error { return server02.ListenAndServe() })
if err := g.Wait(); err != nil { log.Fatal(err) } }
|