(gin)微服务简单例子
gin
https://www.cnblogs.com/jakelin/p/15604267.html
https://gin-gonic.com/zh-cn/docs/quickstart/
https://pkg.go.dev/github.com/gin-gonic/[email protected]#RouterGroup.StaticFile
可能会涉及到的其他包:
net/http
os
render(内置了
binding(内置了
解决gin无法安装问题
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct
# 生成 mod 文件(切换到模块根目录)
go mod init modulename
# 清理无效依赖,增加缺失依赖
go mod tidy
go get -u github.com/gin-gonic/gin
简单案例
第一个程序
package main
import (
//"fmt"
"net/http"
"os"
"github.com/gin-gonic/gin"
)
func main(){
engine := gin.Default() //生成一个实例
engine.GET("ping",func(c *gin.Context) {
c.String(http.StatusOK,"pong") //申明一个路由,告诉gin触发的url和要显示的信息
})
engine.Run(port()) //运行
}
func port() string{
port := os.Getenv("PORT") //获取名为PORT的参数
if len(port) == 0 {
port = "8080"
}
return ":" + port
}
运行这个程序,会看到程序监听在8080端口,我们用浏览器去访问8080
我们再尝试访问我们设置的ping,可以看到回复了一个我们设置的pong
加一点小细节
package main
import (
"net/http"
"os"
"github.com/gin-gonic/gin"
)
func port() string {
port := os.Getenv("PORT")
if len(port) == 0 {
port = "8080"
}
return ":" + port
}
type Book struct {
Title string `json:"书名"`
Author string `json:"作者"`
Date string `json:"出版日期,omitempty"`
ISBN string `json:"isbn"`
}
var Booklist = map[string]Book{
"1101100011": {Title: "go语言圣经", Author: "Alan A. A. Donovan, Brian W. Kernighan", Date: "2016-03", ISBN: "1101100011"},
"1145141919": {Title: "U.N", Author: "anyone", ISBN: "1145141919"},
}
func AllBooks() []Book { //把booklist从map转为切片输出
value := make([]Book, len(Booklist))
inx := 0
for _, book := range Booklist {
value[inx] = book
inx++
}
return value
}
func Getbook(isbn string) (Book, bool) {
book, isfound := Booklist[isbn]
return book, isfound
}
func Update(isbn string, book Book) bool { //如果这本书存在,那么更新
_, exist := Booklist[isbn]
if exist {
Booklist[isbn] = book
}
return exist
}
func Create(book Book) (string, bool) { //创建书本
_, exist := Booklist[book.ISBN]
if exist {
return "", false
} else {
Booklist[book.ISBN] = book
return book.ISBN, true
}
}
func Delete(isbn string) bool {
_, exist := Booklist[isbn]
if exist {
delete(Booklist, isbn)
return true
} else {
return false
}
}
func main() {
engine := gin.Default()
engine.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
engine.GET("hello", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "hello gin!"}) //type H map[string]any
})
engine.LoadHTMLGlob("./*.html") //加载并渲染html,另外有个类似的 LoadHTMLFiles ,但是需要一个个列举文件
engine.StaticFile("/ico", "./favicon.ico") //将某个文件作为静态资源访问
engine.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{"title": "here is the main website!"}) //type H map[string]any
})
engine.GET("/api/books", func(c *gin.Context) { //以json格式打印所有的书
c.JSON(http.StatusOK, AllBooks())
})
engine.GET(("/api/books/:isbn"), func(c *gin.Context) { //通过isbn查找书
isbn := c.Params.ByName("isbn") //byname会返回匹配name的第一个参数的值,如果没有那就返回空字符串
//isbn := c.Query("isbn") //也可以使用c.Query(),用?传参,但是注意路由部分不能和其他的重复
book, found := Getbook(isbn)
if found {
c.JSON(http.StatusOK, book)
}
})
engine.PUT("/api/books/:isbn", func(c *gin.Context) { //如果存在,那么更新
isbn := c.Params.ByName("isbn")
var book Book
if c.BindJSON(&book) == nil { //bind系列方法的目的是自动提取HTTP请求中的各种参数到结构体中,内部调用ShouldBindWith和MustBind,如果发生错误会400返回
exist := Update(isbn, book)
if exist {
c.Status(http.StatusOK)
} else {
c.Status(http.StatusNotFound)
}
}
})
engine.POST("/api/books", func(c *gin.Context) { //上传书本
var book Book
if c.BindJSON(&book) == nil {
isbn, ok := Create(book)
if ok {
c.Header("new-book's-location", "/api/books/"+isbn)
c.Status(http.StatusCreated)
} else {
c.Status(http.StatusConflict)
}
}
})
engine.DELETE("/api/books/:isbn", func(c *gin.Context) {
isbn := c.Params.ByName("isbn")
status := Delete(isbn)
if status {
c.Status(http.StatusOK)
} else {
c.Status(http.StatusNotFound)
}
})
engine.Run(port())
}
/*
[GIN-debug] GET / --> main.main.func3 (3 handlers)
[GIN-debug] GET /api/books --> main.main.func4 (3 handlers)
[GIN-debug] GET /api/books/:isbn --> main.main.func5 (3 handlers)
[GIN-debug] PUT /api/books/:isbn --> main.main.func6 (3 handlers)
[GIN-debug] POST /api/books --> main.main.func7 (3 handlers)
[GIN-debug] DELETE /api/books/:isbn --> main.main.func8 (3 handlers)
*/
//当然,这样写十分不安全,只有在这个练习题里面才能这么干,生产环境这么写黑客们就要笑嘻了
使用postman来测试这个api是否正常
GET获取书籍列表
通过isbn找书
通过isbn更新书本信息,要注意这里使用json格式的话得用编码后的字段
上传书本信息
删除书本
在docker上部署微服务
FROM golang:latest #表明使用的底层镜像
#RUN apt update && apt install git #pull下来的镜像有git就不用装
#RUN go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.io,direct && go env -w GOSUMDB=off && go install github.com/gin-gonic/[email protected] && mkdir /go/src/mircoservice-1 2> /dev/null
RUN go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.io,direct && go env -w GOSUMDB=off && mkdir /go/src/mircoservice-1 && cd /go/src/mircoservice-1 && git clone https://github.com/gin-gonic/gin.git && go mod init && go mod tidy && go get -u github.com/gin-gonic/gin
ENV SOURCES /go/src/mircoservice-1/
COPY . ${SOURCES}
RUN cd ${SOURCES} && CGO_ENABLED=0 go build ./example.go
WORKDIR ${SOURCES}
CMD ${SOURCES}example
EXPOSE 8080 #这只是一个声明,没有实际的端口映射作用
go get 国内即使设置了代理网也很差,可能得多试几次才能成功,如果换成go install会因为包不是main而编译失败退出导致镜像构建失败
[root@iZbp15ywdll3dqiq4ija6lZ go-example]# docker run -it -d -p 8080:8080 go-service:v3
7b1e634789394d0118b1d1222bae95de4e21f1ff6d2aeb23746cde0560a948e3
[root@iZbp15ywdll3dqiq4ija6lZ go-example]# curl 127.0.0.1:8080
<h1>hello!</h1></br>
<h2>here is the main website!</h2>
<b>enjoy your day!</b></br>[root@iZbp15ywdll3dqiq4ija6lZ go-example]#
评论已关闭