用Go语言标准库实现Web服务之创建路由

 更新时间:2023年05月21日 10:27:49   作者:LightSaid  
在上一节中创建了项目,这篇文章主要介绍如何用Go语言标准库创建路由,文中有详细的代码示例,对大家的学习或工作有一定的帮助,感兴趣的同学可以参考下

在上一节中创建了项目;现在打开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语言 创建路由的资料请关注脚本之家其它相关文章!

相关文章

  • go中string、int、float相互转换的实现示例

    go中string、int、float相互转换的实现示例

    本文主要介绍了go中string、int、float相互转换的实现示例,文中根据实例编码详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Go语言time库核心用法与避坑指南

    Go语言time库核心用法与避坑指南

    文章介绍了Go语言的time库,该库提供全面的时间处理功能,文章详细说明了time库的核心类型Time、常用方法、格式化与解析、时区管理以及定时器的使用,感兴趣的朋友跟随小编一起看看吧
    2026-01-01
  • 使用Go语言创建一个简单的HTTP服务器的示例代码

    使用Go语言创建一个简单的HTTP服务器的示例代码

    Go语言天生支持网络编程,其标准库 net/http 内置了完整的 HTTP 协议处理能力,语法简洁、性能优越,本文我们将从零开始,用Go语言构建一个基础的 HTTP 服务器,掌握Go在服务端开发中的关键能力,需要的朋友可以参考下
    2025-07-07
  • GO语言支付宝沙箱对接的实现

    GO语言支付宝沙箱对接的实现

    本文介绍了如何使用GO语言对接支付宝沙箱环境,包括秘钥生成、SDK安装和代码实现等步骤,详细内容涵盖了从秘钥生成到前端代码的每个阶段,为开发者提供了一条清晰的指引
    2024-09-09
  • Go 切片copy()函数的用法与原理详解

    Go 切片copy()函数的用法与原理详解

    本文详细剖析Go语言切片复制的核心API copy()函数,涵盖基础用法、目标切片长度、复制子切片、目标切片为空、合并切片、与append对比及实战应用,通过具体示例,解释了完全独立复制、不自动扩容、返回值含义等关键知识点
    2026-05-05
  • Go语言Select chan用法小结

    Go语言Select chan用法小结

    select语句是Go语言中用于处理多个通道操作的关键字,它允许你在多个通道上进行非阻塞的选择操作,本文就详细介绍一下如何使用,感兴趣的可以了解一下
    2023-09-09
  • 使用go xorm来操作mysql的方法实例

    使用go xorm来操作mysql的方法实例

    今天小编就为大家分享一篇关于使用go xorm来操作mysql的方法实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • Golang基础之函数使用(参数传值)实例详解

    Golang基础之函数使用(参数传值)实例详解

    这篇文章主要为大家介绍了Golang基础之函数使用(参数传值)实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • Go语言关于几种深度拷贝(deepcopy)方法的性能对比

    Go语言关于几种深度拷贝(deepcopy)方法的性能对比

    这篇文章主要介绍了Go语言关于几种深度拷贝(deepcopy)方法的性能对比,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • golang的tunny的用法示例教程

    golang的tunny的用法示例教程

    这篇文章主要为大家介绍了golang的tunny的用法示例教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07

最新评论