用Go语言标准库实现Web服务之创建路由
作者:LightSaid
在上一节中创建了项目;现在打开internal/app/app.go
中创建一个application结构体来管理api服务:
// application 一个管理API服务的结构体 type application struct { cfg config.AppConfig store dbrepo.Repository }
在上面其中 dbrepo.Repository
数据库操作层,先创建一个结构体,后续实现
- internal/dbrepo/repository.go
type Repository struct { } func NewRepository(db *sql.DB) Repository { return Repository{ Book: NewBookRepo(db), } }
在这里我希望application
实例管理整个api服务,包括启动服务、关闭服务、路由注册、路由处理、中间件等
功能。
因此有一个newApplication
函数,做初始化服务工作,首先要初始化就是加载配置文件,在系统中配置文件是一个关键信息,要最先初始化,从而保证后面用到配置的对象能够正常创建。
func newApplication() *application { // 解析命令行参数 var cfgPath string flag.StringVar(&cfgPath, "path", "configs/app.json", "config 配置文件路径") flag.Parse() // 加载app配置 cfg, err := config.LoadAppConfig(cfgPath) if err != nil { log.Fatal(err) } // 格式化输出一下配置,仅开发模式下 cfg.Println() // 设置全局日志 logger.SetGlobalLogger() // 连接mysql db, err := sql.Open("mysql", cfg.DSN) if err != nil { log.Fatal(err) } // ping 确定能连接上数据库 if err = db.Ping(); err != nil { log.Fatal(err) } // 设置最大链接数、最大空闲数和最大空闲时间 db.SetMaxOpenConns(cfg.MaxOpenConns) db.SetMaxIdleConns(cfg.MaxIdleConns) db.SetConnMaxIdleTime(cfg.MaxIdleTimeToDuration()) a := &application{ cfg: cfg, store: dbrepo.NewRepository(db), } return a }
上面函数一开始使用flag
库来解析命令行参数,函数解析:flag.StringVar(解析后赋值给谁,参数名字,参数默认值,参数提示语)
,最后一定要用flag.Parse()
解析参数。那么这个命令参数是怎么用的呢?简单,在启动的时候如下:
go run main.go -path=configs/app.jso
命令行参数使用介绍完毕,在这里顺便另一个场景,例如在别人代码中经常看到这样一个用法,如:
env := os.Getenv("APP_ENV")
那么这个APP_ENV
环境变量在哪里配置的呢?这里介绍两种情况设置:
- 1. 在代码中设置 os.Setenv(key string, value string) - 2. 启动程序通过命令设置如: APP_ENV=dev go run main.go
另外在这里我修改了maxOpenConns、maxIdleConns、maxIdleTime 配置,目前来讲对一个中小型项目来说刚运营时,这个配置是最合适的。后续可以根据服务流量调整。
{ ... "maxOpenConns": 25, "maxIdleConns": 25, "maxIdleTime": "5m" }
接下来就是创建一个http.Server
实例,使用这个实例来启动API服务。
func (a *application) serve() error { var address = fmt.Sprintf("0.0.0.0:%d", a.cfg.Port) // 创建 http.Server 用来启动 Web Server srv := http.Server{ Addr: address, Handler: a.routes(), IdleTimeout: time.Minute, ReadTimeout: 15 * time.Second, WriteTimeout: 30 * time.Second, } logger.InfoLog.Println("Starting API Server on: " + address) return srv.ListenAndServe() } func Serve() error { return newApplication().serve() }
首先在这里func (a *application) serve()
用于内部创建一个 http.Server
和启动server; 而 func Serve()
是提供外部的main.go
中main函数调用。 很多开源项目都是这个做法,对导出去函数简化。
然后使用http.NewServeMux()
创建路由:
- internal/app/routes.go
package app import "net/http" func (a *application) routes() http.Handler { mux := http.NewServeMux() mux.HandleFunc("/v1/book", a.tmp) // GET 获取一个图书 book?id=1 mux.HandleFunc("/v1/book/post", a.tmp) // POST 创建一个图书 mux.HandleFunc("/v1/book/put", a.tmp) // PUT 更新一个图书 mux.HandleFunc("/v1/book/del", a.tmp) // DELETE 删除一个图书 mux.HandleFunc("/v1/book/list", a.tmp) // GET 获取图书列表 list?page_idx=1&pageNum=10 return mux } func (a *application) tmp(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "%s:%s", r.Method, r.RequestURI) }
最后就是启动程序~
- main.go
package main import ( "log" "github.com/lightsaid/ebook/internal/app" ) func main() { if err := app.Serve(); err != nil { log.Fatal(err) } }
人生苦短 Let's Go
以上就是用Go语言标准库实现Web服务之创建路由的详细内容,更多关于Go语言 创建路由的资料请关注脚本之家其它相关文章!