GO语言工程实践课后作业 | 青训营

56 阅读3分钟

课后实践

课后实践要求

  • 发布话题和回帖
  • 本地ID生成需要保证不重复,唯一性
  • Append文件,更新索引

Go Module实践

Go需要使用 1.11 及以上版本。

  • 需要将环境变量 GO111MODULE 设置为 on,这样才能启用 Go Module 功能。set GO111MODULE =onset GOPROXY=goproxy.io(win环境下的国内代理)

  • 在一个项目中启用 Go Module 后,可以通过以下步骤进行包依赖管理:

  • 在项目根目录下执行 go mod init 模块路径 命令来初始化一个新的模块。例如:go mod init myapp 将会创建一个名为 myapp 的模块,并生成一个默认的 go.mod 文件。

  • 执行 go mod tidy 命令来自动分析代码中的依赖关系,并更新当前模块的 go.mod 文件。这个命令会根据代码中的实际引用,自动添加和删除模块的依赖关系。

  • 执行 go mod vendor命令来将所有依赖项复制到项目的 vendor 目录中。这样可以确保项目的构建过程中使用的是 vendor 目录中的依赖项,而不是全局的 GOPATH 下的依赖项。

Go Module 提供了更灵活和可靠的包管理方式,可以帮助开发者更好地管理项目的依赖关系,并且能够确保每个项目在不同环境中的构建结果一致。它的出现使得 Go 语言的包管理更加现代化和便捷化,也受到了开发者的广泛欢迎和推崇。

安装引入Gin框架

  • 下载并安装 gin:

$ go get -u github.com/gin-gonic/gin

  • 将 gin 引入到代码中:

import "github.com/gin-gonic/gin"

目录结构

  • controller控制层
  • data数据库
  • repository 数据层
  • service
  • service.go

实战GO

需求:

  • 支持发布帖子
  • 生成ID不重复、唯一性
  • 更新索引

以下是实践的代码

创建启动类

package main ​ import ( _ "github.com/Moonlight-Zhao/go-project-example/cotroller" "github.com/Moonlight-Zhao/go-project-example/repository" "github.com/Moonlight-Zhao/go-project-example/router" "github.com/Moonlight-Zhao/go-project-example/utils" ) ​ func main() { utils.InitConfig() utils.InitMysql() repository.Init() router := router.SetupRouter() // 启动服务器 router.Run(":8080") ​ }

创建router包和类

package router ​ import ( "github.com/Moonlight-Zhao/go-project-example/service" "github.com/gin-gonic/gin" ) ​ func SetupRouter() *gin.Engine { router := gin.Default() // 定义路由和处理函数 router.POST("/topic", service.Insert) return router } ​

在config包下创建yml文件

mysql: url: user:password@(localhost:port)/data?charset=utf8mb4&parseTime=True&loc=Local

在utils包下创建初始化类

package utils ​ import ( "fmt" "github.com/spf13/viper" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" "log" "os" "time" ) ​ func InitConfig() { ​ //设置配置文件的名称为 "app" viper.SetConfigName("app") ​ //添加配置文件的路径为 "config" viper.AddConfigPath("config") ​ //读取配置文件并将其加载到 viper 中。 err := viper.ReadInConfig() if err != nil { fmt.Println(err) } } ​ var DB *gorm.DB ​ func InitMysql() { //自定义日志模板打印sql语句 newLogger := logger.New( log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ SlowThreshold: time.Second, LogLevel:      logger.Info, Colorful:      true, }, ) DB, _ = gorm.Open(mysql.Open(viper.GetString("mysql.url")), &gorm.Config{Logger: newLogger}) } ​

repository

package repository ​ import ( "github.com/Moonlight-Zhao/go-project-example/utils" "log" "sync" ) ​ type Topic struct { Id         int64  json:"id" Title      string json:"title" Content    string json:"content" CreateTime int64  json:"create_time" } type TopicDao struct { } ​ var ( topicDao  *TopicDao topicOnce sync.Once ) ​ func (Topic) TableName() string { return "topic" } ​ func NewTopicDaoInstance() *TopicDao { topicOnce.Do( func() { topicDao = &TopicDao{} }) return topicDao } ​ func (*TopicDao) QueryTopicById(id int64) *Topic { return topicIndexMap[id] } ​ func (*TopicDao) Insert(topic Topic) error { result := utils.DB.Create(&topic) if result.Error != nil { // 插入失败,处理错误情况 log.Println("插入失败:", result.Error) return result.Error } Init() return nil } ​ ​ func (*TopicDao) findAllTopics() ([]Topic, error) { var topics []Topic result := utils.DB.Find(&topics) if result.Error != nil { return nil, result.Error } return topics, nil } ​

索引初始化

package repository ​ var ( topicIndexMap map[int64]*Topic postIndexMap  map[int64][]*Post ) ​ func Init() error { if err := initTopicIndexNewMap(); err != nil { return err } ​ return nil } ​ ​ // 从数据库中读取表来初始化索引 func initTopicIndexNewMap() error { rows, err := topicDao.findAllTopics() if err != nil { return err } ​ topicTmpMap := make(map[int64]*Topic) ​ for _, topic := range rows { topicTmpMap[topic.Id] = &topic } ​ // 将结果存储到全局变量 topicIndexMap 中 topicIndexMap = topicTmpMap return nil } ​

service层

package service ​ import ( "github.com/Moonlight-Zhao/go-project-example/repository" "github.com/gin-gonic/gin" "net/http" "time" ) ​ func Insert(context *gin.Context) { // 接收form表单数据 title := context.PostForm("title") content := context.PostForm("content") ​ currentTime := time.Now() createTime := currentTime.Unix() ​ u1 := repository.Topic{ Id:         0, Title:      title, Content:    content, CreateTime: createTime, } topicDao := repository.NewTopicDaoInstance() err := topicDao.Insert(u1) // repository. if err != nil { repository.Init() context.JSON(http.StatusBadRequest, gin.H{"msg": "发布失败"}) } else { repository.Init() context.JSON(http.StatusOK, gin.H{"msg": "发布成功"}) } }

总结

这个实践完成起来对我来说相当有难度,但是学到的东西也很多,对go语言的熟练度++,跟java中springboot相似,甚至更简单,后面还需要多加实践练习才能更加熟练。