eddycjy / go-gin-example Goto Github PK
View Code? Open in Web Editor NEWAn example of gin
License: MIT License
An example of gin
License: MIT License
routers里面验证用户名密码,这样验证会存在问题的,加入我用户名密码为空呢
又来麻烦了,尴尬学艺不精.
开始按照 gorm:Issues1965实现了接近的效果.
半月前也提了一个Issues但似乎无人知晓解答.
看下源码心想在 Scan之前执行,Find将值全部查到. s.value
Set 就会有tag表的数据,可还是不可以.
如果有时间麻烦帮忙救救强迫症.(去掉strcut中无用的字段)
var topics []*MResult
var topics2 []*Topic
err := db.Select("id,name").Preload("Tags", func(db *gorm.DB) *gorm.DB {
return db.Select("id,name,tag.topic_id")
}).Where(maps).Find(&topics2).Scan(&topics).Error
我目前实现的是:
(查询结果:结构有些臃肿,想要的效果是只显示select中的内容(红箭头指向的))
gorm 查询语句
// err := db.Select("id,name").Preload("Tags", func(db *gorm.DB) *gorm.DB {
// return db.Select("id,name,tag.topic_id")
// }).Where(maps).Find(&topics).Error
在网上查找是用Scan 解决.
但是不执行查询tag表语句了. 关联效果好像因为新的struct
类失效了.
err := db.Select("id,name").Model(&Topic{}).Select("id,name").Preload("Tags", func(db *gorm.DB) *gorm.DB {
return db.Select("id,name,tag.topic_id")
}).Where(maps).Scan(&topics).Error
重新pull下,将数据库数据更新下.sql文件
涉及到的方法入口.
routers/api/v1/topic.go -> service/topic_service/topic.go -> models/topic.go->GetTopics()
切换 service/topic_service/topic.go->GetAll() 返回值为 []*models.Topic
运行打开 http://localhost:8000/swagger/index.html
执行 获取主题列表
或者 利用 curl
curl -X GET "http://localhost:8000/api/v1/topics" -H "accept: application/json"
Thx.
vendor\github.com\fvbock\endless\endless.go:64:3: undefined: syscall.SIGUSR1
vendor\github.com\fvbock\endless\endless.go:65:3: undefined: syscall.SIGUSR2
vendor\github.com\fvbock\endless\endless.go:68:3: undefined: syscall.SIGTSTP
vendor\github.com\fvbock\endless\endless.go:111:5: undefined: syscall.SIGUSR1
vendor\github.com\fvbock\endless\endless.go:112:5: undefined: syscall.SIGUSR2
vendor\github.com\fvbock\endless\endless.go:115:5: undefined: syscall.SIGTSTP
vendor\github.com\fvbock\endless\endless.go:119:5: undefined: syscall.SIGUSR1
vendor\github.com\fvbock\endless\endless.go:120:5: undefined: syscall.SIGUSR2
vendor\github.com\fvbock\endless\endless.go:123:5: undefined: syscall.SIGTSTP
vendor\github.com\fvbock\endless\endless.go:224:3: undefined: syscall.Kill
vendor\github.com\fvbock\endless\endless.go:224:3: too many errors
第一次执行
UPDATE `topic` SET `modified_at` = '1543033067', `modified_by` = '1', `name` = '主题名称', `state` = '1' WHERE `topic`.`deleted_at` IS NULL AND ((id = '1' ))
第五次执行
UPDATE `topic` SET `modified_at` = '1543033071', `modified_by` = '1', `name` = '主题名称', `state` = '1' WHERE `topic`.`deleted_at` IS NULL AND ((id = '1' ) AND (id = '1' ) AND (id = '1' ) AND (id = '1' ) AND (id = '1' ))
附带项目地址。 麻烦大佬了。谢谢。
gin-blog
有些接口需要获取用户信息,不知道这个根据jwt怎么实现,有人提议,在加密生辰token之前查出用户信息将id缓存,不知道该如何实现
vendor\github.com\fvbock\endless\endless.go:64:3: undefined: syscall.SIGUSR1
vendor\github.com\fvbock\endless\endless.go:65:3: undefined: syscall.SIGUSR2
vendor\github.com\fvbock\endless\endless.go:68:3: undefined: syscall.SIGTSTP
vendor\github.com\fvbock\endless\endless.go:111:5: undefined: syscall.SIGUSR1
vendor\github.com\fvbock\endless\endless.go:112:5: undefined: syscall.SIGUSR2
vendor\github.com\fvbock\endless\endless.go:115:5: undefined: syscall.SIGTSTP
vendor\github.com\fvbock\endless\endless.go:119:5: undefined: syscall.SIGUSR1
vendor\github.com\fvbock\endless\endless.go:120:5: undefined: syscall.SIGUSR2
vendor\github.com\fvbock\endless\endless.go:123:5: undefined: syscall.SIGTSTP
运行的时候出现这个错误
main.go 22行的BasePath填 ‘/’ 会不会比较好,
不然在swagger/index.html页面的里面测试测口的时候地址是
http://127.0.0.1:8000/v1/api/v1/articles?tag_id=1,
有两个v1
claims, err := util.ParseToken(token)
if err != nil {
code = e.ERROR_AUTH_CHECK_TOKEN_FAIL
} else if time.Now().Unix() > claims.ExpiresAt {
code = e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT
}
这块逻辑好像有点问题。如果token过期的话,err就不为空,里面也会有过期错误
if !tokenClaims.Valid {
if ve, ok := err.(*jwt.ValidationError); ok {
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
code = e.ERROR_AUTH_TOKEN
} else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 {
code = e.ERROR_AUTH_TOKEN_TIMEOUT
}
}
}
我现在是这样处理的
在response.go中第15行代码 "code": httpCode, 此处应该"code": errCode更合理吧!
另外还有个疑问:
为什么不把service中的方法直接封装到model中为结构方法,v1/api目录相当于controller, 这样在v1/api中直接调用model的方法不是更好吗?
我看到你在service里面从新定义了结构,和对应model类似,作用仅仅只是用来接收v1/api传递下来的参数, 那为什么不直接用model呢,如果service里面定义的struct意图是用于逻辑数据模型,完全可以创建一个vo目录,里面放逻辑层的model,比如UserVo.go, 因为我在看service代码时发现,struct既用来接收controller的参数,也用于返回给用户的数据模型,这样感觉有一点杂乱,这里只是个人见解,希望和你交流一下。
redigo 使用 hgetall后怎么处理结果呢
RT:大佬有线上部署么?
https://github.com/EDDYCJY/go-gin-example/blob/master/pkg/app/response.go
这个文件
func (g *Gin) Response(httpStatusCode, errCode int, data interface{}) (c *gin.Context) {
g.Context.JSON(httpStatusCode, map[string]interface{}{
"code": errCode,
"msg": e.GetMsg(errCode),
"data": data,
})
return
}
写成这样 就不用在router controller里一直去return了。之前的写法有时忘记return会继续执行。
如题,想问一下,包名以下划线分割不太好吧。
这个框架及教程很棒,但我对后端和前端如何进行交互不太清楚,比如后端怎么从前端取数据及提供数据给前端,如能增加一些前端的实例页面就好了
JWT的payload中不应该填入密码,因为这段数据只是使用了base64编码了下。鉴权时,也不需要检查密码,因为这个token一定是该系统发出的,JWT 是包含签名的
从你的segmentfault文章中拿到以下token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJwYXNzd29yZCI6InRlc3QxMjM0NTYiLCJleHAiOjE1MTg3MjQ2OTMsImlzcyI6Imdpbi1ibG9nIn0.KSBY6TeavV_30kfmP7HWLRYKP5TPEDgHtABe9HCsic4
python: 由于该base64编码数据长度模4为3,则后面填充一个'='
base64.b64decode("eyJ1c2VybmFtZSI6InRlc3QiLCJwYXNzd29yZCI6InRlc3QxMjM0NTYiLCJleHAiOjE1MTg3MjQ2OTMsImlzcyI6Imdpbi1ibG9nIn0=")
获取到
{"username":"test","password":"test123456","exp":1518724693,"iss":"gin-blog"}
你的仓库中 根目录下 main.go 和 cron.go 中都有main入口,导致 go get时 报错
go/src/github.com/EDDYCJY/go-gin-example/main.go:21:6: main redeclared in this block
previous declaration at go/src/github.com/EDDYCJY/go-gin-example/cron.go:12:6
go/src/github.com/EDDYCJY/go-gin-example/main.go:28:23: main.func1 redeclared in this block
previous declaration at go/src/github.com/EDDYCJY/go-gin-example/cron.go:16:27
配置文件go-gin-example/conf/app.ini中,设定的“JwtSecret = 233”不起作用;
可能问题出在go-gin-example/pkg/util/jwt.go中,设定全局变量JwtSecret这一句。
var jwtSecret = []byte(setting.AppSetting.JwtSecret)
应该是因为golang中是先导入包,再执行main.go中的init()
原代码执行的顺序为:
jwtSecret作为util的全局变量导入main.go中,将setting.AppSetting.JwtSecret赋值给jwtSecret,此时setting.AppSetting.JwtSecret为空;
再执行main.go中的init(),给setting.AppSetting.JwtSecret赋值为233,jwtSecret一直都没有赋值成功。
不知道是否是这样,望赐教。
看到比如 package article_service 里边的, 查了 Article 单个或列表都会去设置 redis 缓存, 类似:
gredis.Set(key, article, 3600)
gredis.Set(key, articles, 3600)
但是, 没有看到哪里有过期, 是只能靠这个 3600s 吗? 如果数据库更新了某个 Article 的话, 取到的是不是就是旧的数据而不是数据库最新的数据?
控制台输出(unsupported function BeforeCreate)
大佬下面的 err := db.Select("id").Where("name = ? AND deleted_on = ? ", name, 0).First(&tag).Error
应该是db.Select("name")吧?
func ExistTagByName(name string) (bool, error) {
var tag Tag
err := db.Select("id").Where("name = ? AND deleted_on = ? ", name, 0).First(&tag).Error
if err != nil && err != gorm.ErrRecordNotFound {
return false, err
}
if tag.ID > 0 {
return true, nil
}
return false, nil
}
如题。我用dep工具,无法初始化~~~还烦请帮忙看下~~~
因为我是搞前端的,对后端的了解仅限于MVC,所以看到这个项目就开始找controller,没找到,发现业务逻辑好像是写在了routers/api目录下,这样做是基于什么考虑呢?是go框架的惯例吗。。。我内心有点不习惯,求解脱。。
首先感谢这个项目的作者,给了我入门学习go语言十分有效的帮助。
我的困惑就是关于“封装度”的问题,和我接触到的前端项目比起来呢,这个项目是倾向于把各种功能封装到函数,然后再调用的。
举一处例子,比如在这里
判断文件是否存在,用到了CheckMergedImage函数,但是这个函数其实就是把判断文件是否存在做了封装,那为何不把它封装的内容直接写到if语句后面呢,至少这样代码量看起来少了,而且阅读起来也不难。
这种处处皆函数的**是一种设计模式,还是最佳实践,还是为了统一项目风格,或是作者的个人风格?
因为我个人刚接触这个,怕走弯路,所以想把代码之外的许多东西整明白。
大佬大佬,总感觉自己写的测试不太对,想参考对比下..
几点建议:
1.Token获取应该使用post方式,Token验证应加在HTTP Header头部
2.Router的swagger注解有点问题,添加等POST接口应该使用body模式,直接添加
3.用户密码应该使用md5加密(看已经函数写了没用)
疑惑:
1.业务错误代码调用有问题,已提交pr #46
我在构建models文件里的tag文件运行时报了
```invalid memory address or nil pointer dereference``
这个错误,可是我是按照做着代码编写的,请问是什么原因呢?gorm包我也引入了,使用的gomod的包管理工具
model和service里都有一份struct 有点困惑 可以解释下出于什么考量吗
麻烦问下第26行
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
报错:
cannot use sse.Event literal (type sse.Event) as type render.Render in argument to c.Render: sse.Event does not implement render.Render (missing WriteContentType method)
是怎么回事呢?
{
"code": 200,
"msg": "ok",
"data": {
"id": 2,
"created_on": 0,
"modified_on": 0,
"deleted_on": 0,
"tag_id": 3,
"tag": {
"id": 0,
"created_on": 0,
"modified_on": 0,
"deleted_on": 0,
"name": "",
"created_by": "",
"modified_by": "",
"state": 0
},
...
需要把 InitRouter 方法内的 gin.SetMode 放到 gin.New 之前 才能生效么么哒
emm 都不关闭数据库连接的吗
func Set(key string, data interface{}, time int) (bool, error) {
conn := RedisConn.Get()
defer conn.Close()
value, err := json.Marshal(data)
if err != nil {
return false, err
}
reply, err := redis.Bool(conn.Do("SET", key, value))
conn.Do("EXPIRE", key, time)
return reply, err
}
您好,在这个方法中,conn.Do("SET", key, value) 这个返回一个ok,err ,ok一个字符串“ok”,那这里用redis.Bool()方法不是很合适吧。还是我这边测试的问题
package golang.org/x/image/math/fixed: unrecognized import path "golang.org/x/image/math/fixed" (https fetch: Get https://golang.org/x/image/math/fixed?go-get=1: dial tcp 216.239.3
7.1:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host
has failed to respond.)
package golang.org/x/image/font: unrecognized import path "golang.org/x/image/font" (https fetch: Get https://golang.org/x/image/font?go-get=1: dial tcp 216.239.37.1:443: connectex
: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to res
pond.)
[info] replacing callback gorm:update_time_stamp
from /data/go/src/github.com/EDDYCJY/go-gin-example/models/models.go:40
[info] replacing callback gorm:update_time_stamp
from /data/go/src/github.com/EDDYCJY/go-gin-example/models/models.go:41
[info] replacing callback gorm:delete
from /data/go/src/github.com/EDDYCJY/go-gin-example/models/models.go:42
这个是什么原因?
setting.Setup, fail to parse 'conf/app.ini': open conf/app.ini: no such file or directory
新版的swagger 不再支持param类型 而是改为了path类型,在编写api中的文档时把param 更新为 path
为什么API要和Router放在一起?Models里面为什么要放查询方法?设计目的是?
关于 gin.Context 问下,是否可以在这里注册一个对象,然后在api处理请求里面调用这个唯一对象?
請問在目前的架構下
DB transactions 這部分該如何應用呢?
每次 改完gin的代码 都要自己重新go run 下,不太方便.
大佬知道怎样可以实现热更新吗?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.