「Go」Go-搭建IM即时通讯系列文章1-搭建基础框架 通过「Go」Go 组件系列文章,我们已经了解了一些组件的基本使用。下面我们将以实现登录功能为目标来完整的搭建一个基础框架。
和上述步骤一样,我们从配置项搭建开始,在 项目根目录/src/main/ 目录下新建一个 config 目录,用于存放配置文件。在该目录下新建 database、settings 目录,并分别新建 database.go 和 settings.go 文件,用做初始化读取配置(viper)以及初始化数据库操作(grom)。
Viper 读取配置settings.go 提供了读取配置并设置到全局实体提供给其他类使用,代码如下:
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 75 76 77 78 79 80 81 82 83 package settingsimport ( "fmt" "github.com/spf13/viper" "time" ) type Settings struct { Server Server `mapstructure:"server"` Database Database `mapstructure:"db"` } var Setting = &Settings{}type Server struct { Url string `mapstructure:"url"` Port int `mapstructure:"port"` ReadTimeout time.Duration `mapstructure:"readTimeout"` WriteTimeout time.Duration `mapstructure:"writeTimeout"` } var ServerSetting = &Server{}type Database struct { Type string `mapstructure:"type"` User string `mapstructure:"user"` Password string `mapstructure:"password"` Host string `mapstructure:"host"` Name string `mapstructure:"name"` TablePrefix string `mapstructure:"prefix"` } var DatabaseSetting = &Database{}func Setup () { viper.SetConfigName("app" ) viper.SetConfigType("yaml" ) viper.AddConfigPath("src/resource/" ) err := viper.ReadInConfig() if err != nil { panic (fmt.Errorf("读取配置异常: %w" , err)) } fmt.Println("初始化配置文件成功" ) viper.WatchConfig() err = viper.UnmarshalKey("settings" , Setting) if err != nil { panic (fmt.Errorf("读取配置异常,解析失败: %w" , err)) } ServerSetting = &Setting.Server DatabaseSetting = &Setting.Database ServerSetting.ReadTimeout = ServerSetting.ReadTimeout * time.Second ServerSetting.WriteTimeout = ServerSetting.WriteTimeout * time.Second }
该类主要操作
读取配置文件并解析为实体 设置全局变量提供给其他类使用 设置初始值 Gorm 连接数据库database.go 提供了初始化数据库连接的操作,代码如下:
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 package databaseimport ( "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" "log" "os" "star-im/src/main/config/settings" "time" ) var DBS *gorm.DBfunc Setup () { var err error dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local" , settings.DatabaseSetting.User, settings.DatabaseSetting.Password, settings.DatabaseSetting.Host, settings.DatabaseSetting.Name) newLogger := logger.New( log.New(os.Stdout, "\r\n" , log.LstdFlags), logger.Config{ SlowThreshold: time.Second, LogLevel: logger.Silent, IgnoreRecordNotFoundError: true , Colorful: true , }, ) DBS, err = gorm.Open(mysql.Open(dsn), &gorm.Config{ Logger: newLogger, }) if err != nil { panic (fmt.Errorf("初始化数据库异常: %w" , err)) } sqlDB, err := DBS.DB() sqlDB.SetMaxIdleConns(10 ) sqlDB.SetMaxOpenConns(100 ) sqlDB.SetConnMaxLifetime(time.Hour) }
该类主要操作
读取数据库连接配置 初始化数据库连接 定义了 慢 SQL 日志配置 设置了数据库连接池配置 返回全局变量DBS供其他类使用 Init 加载配置在 项目根目录/src/main/config 目录下新建 init.go 文件,用于初始化上面两个配置项。
init.go 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package configimport ( "star-im/src/main/config/database" "star-im/src/main/config/redis" "star-im/src/main/config/settings" ) func Initial () { settings.Setup() database.Setup() }
该文件到时候放在main方法中执行即可
Main 程序入口在 项目根目录 下新建一个 main.go 作为我们作为http程序主入口,参考 gin 章节初始化gin
main.go 代码如下:
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 package mainimport ( "fmt" "log" "net/http" "star-im/src/main/config" "star-im/src/main/config/settings" "star-im/src/main/routers" ) func init () { config.Initial() } func main () { routersInit := routers.Setup() readTimeout := settings.ServerSetting.ReadTimeout writeTimeout := settings.ServerSetting.WriteTimeout endPoint := fmt.Sprintf(":%d" , settings.ServerSetting.Port) maxHeaderBytes := 1 << 20 server := &http.Server{ Addr: endPoint, Handler: routersInit, ReadTimeout: readTimeout, WriteTimeout: writeTimeout, MaxHeaderBytes: maxHeaderBytes, } log.Printf("[info] 启动http服务器侦听 %s" , endPoint) err := server.ListenAndServe() if err != nil { panic (fmt.Errorf("启动服务异常:%w" , err)) } }
该类主要操作
初始化配置 初始化路由配置以及服务基础设置 routers.Setup() ,路由等信息单独放在另外一个目录 routers中来统一管理。
router 路由配置在 项目根目录/src/main/ 目录下新建一个 routers 目录,并按照层级建立 api/v1 两个目录,用于存放路由接口。v1 表示接口版本号,方便后续迭代接口版本。
在 项目根目录/src/main/routers/api 目录下创建 health.go ,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package apiimport ( "github.com/gin-gonic/gin" "star-im/src/main/common/app" ) func Ping (c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "msg" : "成功" , }) }
该类主要做连通性测试,因此直接返回json成功数据
在 项目根目录/src/main/routers 目录下创建 router.go 文件用于初始化路由配置,代码如下
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 package routersimport ( "github.com/gin-gonic/gin" "io" "os" "star-im/src/main/handler" "star-im/src/main/routers/api" ) func Setup () *gin.Engine { r := gin.Default() f, _ := os.Create("gin.log" ) gin.DefaultWriter = io.MultiWriter(f) r.Use(gin.Logger()) r.GET("/ping" , api.Ping) return r }
该类主要操作
初始化路由设置 指定记录日志到文件 指定具体的路由地址以及请求方式和响应函数 这时候我们启动根目录下的 main函数即可启动服务,通过浏览器访问:http://localhost:8081/ping 可以得到返回值
到这一步我们已经能够提供一个提供基础访问的应用,后续我们继续完善应用的内容。