go实践之apiserver搭建

本文主要记录下博主用gin搭建app server的过程,方便后续学习。web框架用的gin,日志用的zap,数据库连接用的mysql driver,配置文件读取用的是viper。整个项目的框架如下:

.
├── app
│ ├── comment.go
│ ├── server.go
│ └── user.go
├── config.toml
├── Gopkg.lock
├── Gopkg.toml
├── LICENSE
├── main.go
├── README.md
├── tool
│ ├── config
│ │ ├── config.go
│ │ └── config_test.go
│ ├── db
│ │ ├── mysql.go
│ │ └── mysql_test.go
│ └── log
│ ├── log.go
│ └── log_test.go
└── vendor
├── github.com
......

main.go作为整个api server 的入口文件,tool文件夹下面存放了日志,数据库,配置文件相关代码。app文件夹里面是api实现相关的代码。

1、配置文件读取

配置文件读取的代码如下:

package config

import(
"fmt"
"github.com/spf13/viper"
) func ParseConfig() error {
viper.SetConfigName("config") // name of config file (without extension)
viper.AddConfigPath("./conf") // call multiple times to add many search paths
viper.AddConfigPath(".") // optionally look for config in the working directory
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
return fmt.Errorf("Fatal error config file: %s \n", err)
}
viper.WatchConfig()
return nil
}

这里只是简单的一个demo,viper还有更多的功能,比如设置默认值 viper.SetDefault("ContentDir", "content"),可以加载环境变量中的值AutomaticEnv(),热更新配置文件 viper.WatchConfig()。具体可以参考官方文档:链接

2、数据连接

本文件主要实现的是数据库连接,以及增删查改操作。具体代码如下:

package db

import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"time"
"github.com/spf13/viper"
"fmt"
) type DbConn struct {
Db *sql.DB
} func InitDbConn()(*DbConn, error) {
dbConn := viper.GetString("Database.DbConn")
db, err := sql.Open("mysql", dbConn)
if err != nil {
return nil, fmt.Errorf("get db connection error")
}
maxOpenConns := viper.GetInt("Database.MaxOpenConn") //从配置文件中获取配置值
maxIdleConns := viper.GetInt("Database.MaxIdleConn")
maxLifetime := viper.GetInt("Database.MaxLifetime") ......//省略部分代码 err = db.Ping()
if err != nil {
return nil,fmt.Errorf("connect to db error")
}else{
dbconn := &DbConn{Db:db}
return dbconn,nil
}
} func (c *DbConn) Insert(sql string, args ...interface{}) (lastInsertId int64, err error) {
res, err := c.Db.Exec(sql, args...)
if err != nil {
return
}
return res.LastInsertId()
}
......//省略部分代码

主要是调用mysql driver根据配置文件配置值连接数据库。

3、日志初始化

日志主要的是uber的zap日志框架,这是一个高性能的日志框架,在这里有点小用它了。也只是一个简单的使用举例。更多功能需要去学习。

package log

import (
"fmt"
"strings" "github.com/spf13/viper"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
) var Logger *zap.SugaredLogger //global logger func InitLog() {
logLevel := viper.GetString("Log.LogLevel")
logName := viper.GetString("Log.LogName")
logAge := viper.GetInt("Log.LogAge")
logSize := viper.GetInt("Log.LogSize") w := zapcore.AddSync(&lumberjack.Logger{
Filename: logName,
MaxSize: logSize, // megabytes
MaxBackups: 3,
LocalTime: true,
MaxAge: logAge, // days
})
zapLogLevel := zap.NewAtomicLevel()
if err := zapLogLevel.UnmarshalText([]byte(strings.ToLower(logLevel))); err != nil {
panic(fmt.Errorf("get config log level:%v config error: %v", logLevel, err))
} .....//此处省略部分代码 logger := zap.New(core, zap.AddCaller())
Logger = logger.Sugar()
Logger.Info("logger init successful!")
}

4、server初始化

主要就是调用配置读取函数,数据库连接和日志初始化函数,再启动http server

package main

import (
"fmt"
"os"
"os/signal"
"syscall" "github.com/zhanben/go_site/app"
"github.com/zhanben/go_site/tool/config"
"github.com/zhanben/go_site/tool/db"
"github.com/zhanben/go_site/tool/log" "go.uber.org/zap"
) func main() {
//Read config file
err := config.ParseConfig()
if err != nil {
panic(fmt.Errorf("Failed to read config file: %s \n", err))
} //Init log
log.InitLog() //Init db connection
db, err := db.InitDbConn()
if err != nil {
panic("connect db error!")
}
log.Logger.Info("Db init successful!") //start http sever
startServer(db)
} .....//此处省略部分代码

5、接口编写

下面是简单的两个接口实现的例子:一个是URL中带有参数,一个没有带的。

package app

import (
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"net/http"
"github.com/zhanben/go_site/tool/db"
) .....//此处省略部分代码 func (u *User) initRouter(r *gin.RouterGroup) {
//在此添加接口
r.GET("/users", u.getAllUsers) //获取所有用户信息
r.GET("/users/:name", u.getOneUser) //根据用户名获取用户详细信息
} func (u *User) getAllUsers(c *gin.Context) {
//构建返回结构体
res := map[string]interface{}{
"Action": "GetAllUserResponse",
"RetCode": 0,
} sql := "select * from user limit 10"
result, err := u.db.Select(sql)
if err != nil {
u.Logger.Error("get user info from db error!")
abortWithError(u.Logger, c, err)
}
res["UserInfo"] = result
c.JSON(http.StatusOK, res)
} func (u *User) getOneUser(c *gin.Context) {
//构建返回结构体
res := map[string]interface{}{
"Action": "GetOneUserResponse",
"RetCode": 0,
}
userName, ok :=c.Params.Get("name")
if !ok {
u.Logger.Error("parameter name must be fixed!")
}
u.Logger.Infof("get user name from url:%s",userName) sql := "select * from user where username=?"
result, err := u.db.Select(sql,userName)
if err != nil {
u.Logger.Error("get user info from db error!")
res["RetCode"]= "-1"
res["Error"] = "user not exist!"
}else{
res["UserInfo"] = result
u.Logger.Info("get one user info successful!")
}
c.JSON(http.StatusOK, res)
}

至此一个简单的go api sever的框架就搭建好了。当然后续还有单元测试的代码需要补充。本文的全部的代码可以到github下载:git clone --branch v0.1 git@github.com:Zhanben/go_site.git

go实践之apiserver搭建的更多相关文章

  1. 从零开始针对 .NET 应用的 DevOps 运营实践 - 运行环境搭建

    一.Overview 最近的一段时间,在公司里我都在进行基于 Jenkins 和 SonarQube 配合已有的 Gitlab 搭建部门的持续集成环境的工作,虽然之前有使用过 GitHub Actio ...

  2. 前端项目模块化的实践1:搭建 NPM 私有仓库管理源码及依赖

    以下是关于前端项目模块化的实践,包含以下内容: 搭建 NPM 私有仓库管理源码及依赖: 使用 Webpack 打包基础设施代码: 使用 TypeScript 编写可靠类库 使用 TypeScript ...

  3. 【机器学习PAI实践一】搭建心脏病预测案例

    一.背景 心脏病是人类健康的头号杀手.全世界1/3的人口死亡是因心脏病引起的,而我国,每年有几十万人死于心脏病. 所以,如果可以通过提取人体相关的体侧指标,通过数据挖掘的方式来分析不同特征对于心脏病的 ...

  4. OceanBase数据库实践入门——手动搭建OceanBase集群

    前言 目前有关OceanBase功能.案例.故事的文章已经很多,对OceanBase感兴趣的朋友都想安装一个数据库试试.本文就是分享初学者如何手动搭建一个OceanBase集群.这也是学习理解Ocea ...

  5. 运维开发实践——基于Sentry搭建错误日志监控系统

    错误日志监控也可称为业务逻辑监控, 旨在对业务系统运行过程中产生的错误日志进行收集归纳和监控告警.似乎有那么点曾相识?没错... 就是提到的“APM应用性能监控”.但它又与APM不同,APM系统主要注 ...

  6. django入门与实践 3-1 环境搭建

    Python 2.7 .Django对2.7.3.5.3.4都是支持的. https://www.djangoproject.com/download/ django对python的兼容情况 pip安 ...

  7. 2. react 编程实践 俄罗斯方块-环境搭建

    1. 创建 demo 目录 mkdir demo 2. 初始化应用 npm init 工程信息 package name : tetris-class-demo version: descriptio ...

  8. go实践之swagger自动生成api文档

    文章目录 go实践之swagger自动生成api文档 1.安装需要用到的包 2.接口代码支持swagger 3. 生成swagger接口 go实践之swagger自动生成api文档 作为一个后端开发, ...

  9. MySQL5.6 GTID新特性实践

    MySQL5.6 GTID新特性实践 GTID简介 搭建 实验一:如果slave所需要事务对应的GTID在master上已经被purge了 实验二:忽略purged的部分,强行同步 本文将简单介绍基于 ...

随机推荐

  1. c#数据结构之Array、ArrayList、List、LinkedList对比分析

    一.前言: 在c#数据结构中,集合的应用非常广泛,无论是做BS架构还是CS架构开发,都离不开集合的使用,比如我们常见的集合包括:Array.ArrayList.List.LinkedList等.这一些 ...

  2. BASH 编程之变量高级篇

    内部变量 • $$与$BASHPID都代表着执行程序的进程 ID,我们可以通过 echo 打印,并用 ps 指令检查得到相同的进程 ID [root@oracle ~]# echo $BASHPID ...

  3. Ubuntu 16.04.4 LTS设置root用户登陆图形界面

    普通用户登陆真是太憋屈,这也不能那也不能,root用户登录就可以肆无忌惮了 本方法采用nano编辑器,ubantu版本Ubuntu 16.04.4 LTS,其他版本应该也一样,下面进入正题 1.终端登 ...

  4. js中call、apply和bind到底有什么区别?

    介绍 在js中,每个函数的原型都指向Function.prototype对象(js基于原型链的继承).因此,每个函数都会有apply,call,和bind方法,这些方法继承于Function. 它们的 ...

  5. Mysql备份还有这么多套路,还不了解下?

    逻辑备份和物理备份 逻辑备份 逻辑备份用于备份数据库的结构(CREAET DATABASE.CREATE TABLE)和数据(INSERT),这种备份类型适合数据量小.跨SQL服务器.需要修改数据等场 ...

  6. 【RocketMQ源码学习】- 5. 消息存储机制

    前言 面试官:你了解RocketMQ是如何存储消息的吗?我:额,,,你等下,我看下这篇文字, (逃 由于这部分内容优点多,所以请哥哥姐姐们自备茶水,欢迎留言! RocketMQ存储设计是高可用和高性能 ...

  7. 堆模板(STL版)

    题目描述 如题,初始小根堆为空,我们需要支持以下3种操作: 操作1: 1 x 表示将x插入到堆中 操作2: 2 输出该小根堆内的最小数 操作3: 3 删除该小根堆内的最小数 输入输出格式 输入格式: ...

  8. 【Android - 控件】之MD - FloatingActionButton的使用

    FloatingActionButton(FAB) 是 Android 5.0 新特性——Material Design 中的一个控件,是一种悬浮的按钮. FloatingActionButton 是 ...

  9. Chapter 05—Advanced data management(Part 2)

    二. 控制流 statement:一个单独的R语句或者是一个复合的R语句: cond:条件表达式,为TRUE或FALSE: expr:数字或字符表达式: seq:数字或字符串的顺序. 1.循环语句:f ...

  10. Mysql多表关系

    mysql多表关系 多表关系是关系型数据库特有的 三种关系 一对一关系 一对多关系 多对多关系 总结 一对一 例子:用户和用户信息 外键设置在用户上,外键字段唯一非空 添加 无级联:先增加被关联表记录 ...