package mainimport "github.com/gin-gonic/gin"func main() {r := gin.Default()r.GET("/ping", func(c *gin.Context) {c.JSON(200, gin.H{"message": "pong",})})r.Run() // listen and serve on 0.0.0.0:8080
}
go mod init gin_grpc
go mod tidy
package routerimport ("gin_grpc/app/controller""github.com/gin-gonic/gin"
)// UserRouter 用户模块的路由
func UserRouter(r *gin.Engine) {r.GET("/index", controller.User.Index)
}// InitRouter 路由注册
func InitRouter(r *gin.Engine) {// 用户相关的路由注册UserRouter(r)
}
package controllerimport ("github.com/gin-gonic/gin"
)// Controller controller基类
type Controller struct{}// UserController 继承controller的user
type UserController struct {Controller
}// User UserController的变量
var User=UserController{
}func (t *UserController)Index(c *gin.Context){c.JSON(200, gin.H{"message": "pong",})return
}
package main
import ("gin_grpc/app/router""github.com/gin-gonic/gin"
)
func main() {//r:=gin.New()//启动gin服务r := gin.Default()//Default returns an Engine instance with the Logger and Recovery middleware already attached.router.InitRouter(r)//注册路由r.Run("127.0.0.1:8089") // listen and serve on 0.0.0.0:8080
}
我们读取mysql,读取redis配置,肯定少不了配置文件
这里,我们使用viper来读取配置文件
相关参考文档
安装vipergo get github.com/spf13/viper
在项目根目录下创建config文件夹,在config下创建base.yaml,因为yaml文件相对来说比json更轻量级
#项目相关配置
app:name: gin_grpcdebug: true
#数据库相关配置
database:driver: mysqlhost: 127.0.0.1port: 3306username: acurd_comdbname: cmspassword: acurd_com
#redis相关配置
redis:host: 127.0.0.1port: 6379
package configimport ("fmt""github.com/fsnotify/fsnotify""github.com/spf13/viper"
)// InitConfig 初始化配置文件
func InitConfig() {viper.AddConfigPath("./config")viper.AddConfigPath(".")//多路径查找viper.SetConfigName("base")viper.SetConfigType("yaml")if err := viper.ReadInConfig(); err != nil {panic(err)}//监控并重新读取配置文件viper.WatchConfig()viper.OnConfigChange(func(e fsnotify.Event) {// 配置文件发生变更之后会调用的回调函数fmt.Println("Config file changed:", e.Name)})
}
package main
import ("gin_grpc/app/router""gin_grpc/config""github.com/gin-gonic/gin"
)
//初始化配置文件
func init() {config.InitConfig()
}
func main() {//r:=gin.New()//启动gin服务r := gin.Default()//Default returns an Engine instance with the Logger and Recovery middleware already attached.router.InitRouter(r)//注册路由r.Run("127.0.0.1:8089") // listen and serve on 0.0.0.0:8080
}
package modelimport ("fmt"_ "github.com/go-sql-driver/mysql""github.com/jinzhu/gorm""github.com/spf13/viper""log"
)// Db 用来承接db变量
var Db *gorm.DB// InitDb 初始化数据库连接
func InitDb()*gorm.DB{var (Username = viper.GetString("database.username")Password = viper.GetString("database.password")Host = viper.GetString("database.host")Port = viper.GetInt("database.port")DbName = viper.GetString("database.dbname"))dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", Username, Password, Host, Port, DbName)fmt.Println(Username)db, err := gorm.Open("mysql", dsn)if err != nil {log.Fatal("数据库连接失败,报错信息"+err.Error())}// 设置连接池,空闲连接db.DB().SetMaxIdleConns(50)// 打开链接db.DB().SetMaxOpenConns(100)// 表明禁用后缀加sdb.SingularTable(true)// 启用Logger,显示详细日志db.LogMode(viper.GetBool("app.debug"))return db
}
package model// Blog 定义博文结构体
type Blog struct {AutoID uint `gorm:"column:auto_id;primary_key;AUTO_INCREMENT"` // IDID string `gorm:"column:id;NOT NULL"` // 业务idTitle string `gorm:"column:title;NOT NULL"` // 标题TitleStyle string `gorm:"column:title_style;NOT NULL"` // 标题样式Thumb string `gorm:"column:thumb;NOT NULL"` // 缩略图Keywords string `gorm:"column:keywords;NOT NULL"` // 关键词Description string `gorm:"column:description;NOT NULL"` // 描述Content string `gorm:"column:content;NOT NULL"` // 内容CreateTime uint `gorm:"column:create_time;default:0;NOT NULL"` // 创建时间UpdateTime uint `gorm:"column:update_time;default:0;NOT NULL"` // 更新时间Author string `gorm:"column:author;NOT NULL"` // 作者Source string `gorm:"column:source;NOT NULL"` // 来源Summary string `gorm:"column:summary;NOT NULL"` // 摘要
}// TableName 标记Blog结构体使用的表名
func (m *Blog) TableName() string {return "cms_blog"
}// BlogModel 用来继承model
type BlogModel struct{
}// GetOne 获取一篇文章
func (m *BlogModel)GetOne(i int)Blog{var blog BlogDb.First(&blog,i)return blog
}
// BlogRouter 博客相关路由
func BlogRouter(r *gin.Engine) {r.GET("/blog/:id", controller.Blog.GetOne)
}
func main() {//r:=gin.New()//启动gin服务r := gin.Default()//Default returns an Engine instance with the Logger and Recovery middleware already attached.model.Db=model.InitDb()defer model.Db.Close()router.InitRouter(r)//注册路由r.Run("127.0.0.1:8089") // listen and serve on 0.0.0.0:8080
}
grpc的入门的例子,我再之前的文章golang入门微服务
中详细的讲过,这里简单记录一下步骤
//我们定义一个博文的数据结构,
syntax="proto3";
package blog;
option go_package="/Users/zhangguofu/website/gin_grpc/app/proto/gen/go;blog";//生成的go文件存放目录在哪;包名叫什么
message Blog {uint32 auto_id = 1; // IDstring id = 2; // 业务idstring title = 4; // 标题string title_style = 5; // 标题样式string thumb = 6; // 缩略图string keywords = 7; // 关键词string description = 8; // 描述string content = 9; // 内容uint32 create_time = 14; // 创建时间uint32 update_time = 15; // 更新时间string author = 16; // 作者string source = 17; // 来源string summary = 18; // 摘要
}
// 定义blog服务
service BlogInfo{//定义方法rpc getBlog(Id) returns(Blog);
}
//定义id的消息类型
message Id{int64 value=1;
}
│ ├── proto
│ │ ├── blog.proto
│ │ └── gen
│ │ └── go
│ │ └── blog
│ │ ├── blog.pb.go
│ │ └── blog_grpc.pb.go
func (t *BlogController) RpcGetOne(c *gin.Context) {id := c.Param("id")id_int, _ := strconv.Atoi(id)//监听端口conn, err := grpc.Dial("localhost:9988", grpc.WithInsecure())if err!=nil {log.Fatal(err)}defer conn.Close()//取到客户端连接client:=blog2.NewBlogInfoClient(conn)//组装结构体blogId:=new(blog2.Id)blogId.Value=int64(id_int)info, _ :=client.GetBlog(context.Background(),blogId)fmt.Println(id)c.JSON(200, gin.H{"message": "success","data": info,})return
}
package mainimport ("context""fmt""github.com/blog-server/proto/gen/go/blog""google.golang.org/grpc""log""net""strconv"
)type Server struct{}
/*** @Description* @Author 老a技术联盟* @Date 2023/2/6 11:48**/
func main() {listen, err := net.Listen("tcp", "localhost:9988")if err != nil {return}//创建grpc服务s:=grpc.NewServer()blog.RegisterBlogInfoServer(s,Server{})if err := s.Serve(listen); err != nil {log.Println("failed to serve...", err)return}
}//继承接口
func (s Server)GetBlog(c context.Context,b *blog.Id) (*blog.Blog, error) {//从mysql中取数据的过程忽略,直接返回结果blog:=new(blog.Blog)blog.Id= strconv.Itoa(int(b.Value))fmt.Printf("接收到的id是:%d",b.Value)blog.Author="grpc返回"return blog,nil
}