课后实践
课后实践要求
- 发布话题和回帖
- 本地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相似,甚至更简单,后面还需要多加实践练习才能更加熟练。