golang gin-gonic和包装文件拆分 [英] golang gin-gonic and splitting files in package

查看:203
本文介绍了golang gin-gonic和包装文件拆分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很新,想去学习,我正在用杜松子酒服务器设置一个应用程序。
我设法让它与主包中的所有东西一起工作,我想用一个包(我管理)中的所有最相关的更好的方式来组织它,并且通过文件拆分每个组CRUD。



所以在init函数的包的main文件中,我定义了:

  Router:= gin.New()
Router.Use(gin.Logger())
Router.Use(gin.Recovery())

以及我可以在包的每个其他文件中像这样使用它:

  v1:= Router.Group(/ api / v1 / todos)
v1.Use(AuthRequired())
{
v1.POST(/,CreateTodo)
v1.GET(/,FetchAllTodo)
v1.GET(/:id,FetchSingleTodo)
v1.PUT( /:id,UpdateTodo)
v1.DELETE(/:id,DeleteTodo)
}

  packagename.Router.Group 

但没有人在工作,我得到:


undefined:Router.Group中的路由器



Staphane
PS:我确实设置了一个如果它在一个文件中,我可以去构建它。






虽然这个解决方案是要将Router变量声明为* gin.Engine,但在编译好的时候,我在Router.Group调用中遇到了一个恐慌错误。



让我发布一些更多的部分代码:

maincode.go:

  package main 

进口(
fmt
./apirest
github.com/braintree/manners


func main(){
fmt.Printf(hello world.\\\

//router.Run()
manners.ListenAndServe(:8080,apirest.Router)
}

然后我将这个apirest软件包分成两个文件:

apirest.go(我做过手动清理,也许我错过了一次导入):

  package apirest 

imp ort(
fmt
github.com/gin-gonic/gin
github.com/braintree/manners
os
os / signal


//路由器倒入路由器
var Router * gin.Engine

/ *
主要功能
* /
func init(){

Router:= gin.New()
Router.Use(gin.Logger())
Router使用(gin.Recovery())
$ bc bc:= make(chan os.Signal,1)
signal.Notify(c,os.Interrupt)
go func() {
for sig:= range c {
// sig是a ^ C,处理它
fmt.Printf(ctl + c catched+ sig.String())
)manners.Close()
}
}()

LoadMonitor()

}

然后处理所有声明的todoCRUD.go文件,todoCRUD.go和apirest.go在相同的子文件夹中(并且可以正常编译):

  package apirest 

import(
fmt
github。 COM /杜松子酒/杜松子酒
gopkg.in/validator.v2
github.com/jinzhu/gorm
strconv
净/ http
time


//待办事项定义待办事项待办事项
类型待办事项结构{
gorm.Model
CreatedAt time.Time
UpdatedAt time.Time
OwnerID int`json:owneridvalidate:nonzero`
URL字符串`json:url`
}

// TransformedTodo版本转换为重新转换无信息
类型TransformedTodo结构{
ID uint`json:id`
CreatedAt time.Time
UpdatedAt time .Time
OwnerID uint`json:ownerid`
URL字符串`json:url`
}

// LoadTodo permet de lancer le mappage todos
func LoadTodo(){
v1:= Router.Group(/ api / v1 / todos)
{
v1.POST(/,CreateTodo)
v1.GET(/,FetchAllTodo)
v1.GET(/:id,FetchSingleTodo)
v1.PU T(/:id,UpdateTodo)
v1.DELETE(/:id,DeleteTodo)
}
}

// CreateTodogénérationd' un todo
func CreateTodo(c * gin.Context){

owner,_:= strconv.Atoi(c.PostForm(ownerid))
todo:= Todo {
OwnerID:owner,
URL:c.PostForm(url),
};
v:= validator.NewValidator()
if errs:= v.Validate(todo); errs!= nil {
errors:= errs。(validator.ErrorMap)
var errOuts [] string
for f,e:=范围错误{
errOuts = append(errOuts ,fmt.Sprintf(\ t - %s(%v)\\\
,f,e))
}
//c.JSON(500,gin.H {Error :errs.Error()})
c.JSON(500,gin.H {Erreur sur le(s)champ(s)::errOuts})
} else {

db,_:= Database()
defer db.Close()
db.Save(& todo)

c.JSON(http.StatusCreated, gin.H {status:http.StatusCreated,message:Todo item created successfully!,resourceId:todo.ID})
}
}

// FetchAllTodo重新获得的乐趣
func FetchAllTodo(c * gin.Context){
var todos [] Todo
var _todos [] TransformedTodo

db ,_:= Database()
defer db.Close()
db.Find(&todos)

if(len(todos)<= 0){
c.JSON(http.StatusNotFound,杜松子酒.H {status:http.StatusNotFound,message:No todo found!})
return
}

//转换建立一个好东东响应,
//首先显示$ champs a ne pas显示
for _,item:=范围todos {
status:= false
if(item.Status == 1 ){
status = true
} else {
status = false
}
_todos = append(_todos,TransformedTodo {ID:item.ID,URL:item。 URL})
}
c.JSON(http.StatusOK,gin.H {status:http.StatusOK,data:_todos})
}

// FetchSingleTodoRécupérationd'un seul todo en fonction de son id
func FetchSingleTodo(c * gin.Context){
var todo Todo
todoID:= c.Param(id )

db,_:= Database()
defer db.Close()
db.First(& todo,todoID)

if(todo.ID == 0){
c.JSON(http.StatusNotFound,gin.H {status:http.StatusNotFound,消息:没有todo发现!))
返回
}

_todo:= TransformedTodo {ID:todo.ID,URL:todo.URL}
c.JSON(http.StatusOK,gin.H {status:http.StatusOK,data:_todo})
}

// UpdateTodo Miseàjour d'un todo
func UpdateTodo(c * gin.Context){
var todo Todo
todoID:= c.Param(id)
db,_:= Database()
defer db.Close()
db.First(&todo,todoID)

if(todo.ID == 0){
c.JSON(http。 StatusNotFound,gin.H {status:http.StatusNotFound,message:No todo found!})
return
}

db.Model(& todo).Update(title,c.PostForm(title))
db.Model(& todo).Update(completed,c.PostForm(completed))
c.JSON(http.StatusOK,gin.H {status:http.StatusOK,message:Todo更新成功!})
}


/ / DeleteTodo禁止使用
func DeleteTodo(c * gin.Context){
var todo Tod o
todoID:= c.Param(id)
db,_:= Database()
defer db.Close()
db.First(& todo, todoID)

if(todo.ID == 0){
c.JSON(http.StatusNotFound,gin.H {status:http.StatusNotFound,message:No todo found!})
return
}

db.Delete(& todo)
c.JSON(http.StatusOK,gin.H {status :http.StatusOK,message:Todo deleted successfully!))
}

想法是为每个实体处理一个xxxxCRUD.go文件,但整个文件夹位于同一个包中。



确切的错误是:


PS D:\www\developpement> go run .\maincode.go [GIN-debug] [警告]
运行调试模式。在生产中切换到释放模式。
- 使用env:export GIN_MODE =释放
- 使用代码:gin.SetMode(gin.ReleaseMode)

panic:运行时错误:无效内存地址或零指针
dereference [signal 0xc0000005 code = 0x0 addr = 0x0 pc = 0x46cc0f]

goroutine 1 [running]:panic(0x831880,0xc04200a080)
C:/Go/src/runtime/panic.go:500 + 0x1af
/ D /www/developpement/apirest.LoadTodo()
D:/ www /developpement/apirest/todoCRUD.go:33 + 0x2f [Router.Group]
/ D /www/developpement/apirest.init.1()
D:/ www /developpement/apirest/apirest.go:73 + 0x220 [LoadTodo()]
/ D /www/developpement/apirest.init()
D:/ www / developpement /apirest/todoCRUD.go:190 + 0x80 [最后一行] main.init()
D:/www/developpement/maincode.go:13 + 0x3a [manners.ListenAndServe(:8080,apirest.Router )]退出状态2


我希望这会有助于解释d!



感谢您的时间和帮助!

Stéphane



in apirest

.go:

  LoadTodo(路由器)

和todoCRUD.go:

  func LoadTodo(r * gin.Engine){ 

并且工作正常......我希望我没有在代码中引入错误。 ..

Stéphane


I am quite new to go and try to learn, I am setting up an application with a gin-gonic server. I managed to have it to work with everything in on main package, I would like to organize it better with all the apirest related in a package (which I manage) AND to split each group CRUD by file.

so in the "main" file of the package within the init function, I defined :

Router := gin.New()
Router.Use(gin.Logger())
Router.Use(gin.Recovery())

and I though that I would be able in each other files of the package to use it like that :

v1 := Router.Group("/api/v1/todos")
v1.Use(AuthRequired())
{
    v1.POST("/", CreateTodo)
    v1.GET("/", FetchAllTodo)
    v1.GET("/:id", FetchSingleTodo)
    v1.PUT("/:id", UpdateTodo)
    v1.DELETE("/:id", DeleteTodo)
}

or

packagename.Router.Group

but none are working and I get :

undefined: Router in Router.Group

Stéphane PS : I did setup a sub folder for the package and I am able to go build it if it's in one file.


I though that the solution was to declare the Router variable as *gin.Engine but while it's compiling fine, I get a panic error on the Router.Group call

let me post some more part of code :

maincode.go :

package main

import (
    "fmt"
    "./apirest"
    "github.com/braintree/manners"
)

func main(){
    fmt.Printf("hello world.\n")
    //router.Run()
    manners.ListenAndServe(":8080", apirest.Router)
}

Then I split the apirest package in 2 files :

apirest.go (I did manually cleanup, maybee I missed an import) :

package apirest

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "github.com/braintree/manners"
    "os"
    "os/signal"
)

//Router pour gérer l'api
var Router *gin.Engine

/*
    MAIN FUNCTION
*/
func init() {

    Router := gin.New()
    Router.Use(gin.Logger())
    Router.Use(gin.Recovery())

    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt)
    go func(){
        for sig := range c {
            // sig is a ^C, handle it
            fmt.Printf("ctl+c catched "+sig.String())
            manners.Close()
        }
    }()

    LoadMonitor()

}

and then the todoCRUD.go file that handle all the declaration, the todoCRUD.go and apirest.go are in the same subfolder apirest (and compile ok) :

package apirest

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "gopkg.in/validator.v2"
    "github.com/jinzhu/gorm"
    "strconv"
    "net/http"
    "time"
)

//Todo definition d'un element todo
type Todo struct {
    gorm.Model
    CreatedAt   time.Time
    UpdatedAt   time.Time
    OwnerID     int    `json:"ownerid"  validate:"nonzero"`
    URL         string `json:"url"`
}

//TransformedTodo version pour le retour d'api sans certaines infos
type TransformedTodo struct {
    ID          uint   `json:"id"`
    CreatedAt   time.Time
    UpdatedAt   time.Time
    OwnerID     uint   `json:"ownerid"`
    URL         string `json:"url"`   
}

//LoadTodo permet de lancer le mappage todos
func LoadTodo(){
    v1 := Router.Group("/api/v1/todos")
    {
        v1.POST("/", CreateTodo)
        v1.GET("/", FetchAllTodo)
        v1.GET("/:id", FetchSingleTodo)
        v1.PUT("/:id", UpdateTodo)
        v1.DELETE("/:id", DeleteTodo)
    }
}

//CreateTodo génération d'un todo
func CreateTodo(c *gin.Context) {

    owner, _ := strconv.Atoi(c.PostForm("ownerid"))
    todo := Todo{
        OwnerID: owner,
        URL: c.PostForm("url"),
    };
    v := validator.NewValidator()
    if errs := v.Validate(todo); errs!=nil {
        errors := errs.(validator.ErrorMap)
        var errOuts []string
        for f, e := range errors {
            errOuts = append(errOuts, fmt.Sprintf("\t - %s (%v)\n", f, e))
        }
        //c.JSON(500, gin.H{"Error": errs.Error()})
        c.JSON(500, gin.H{"Erreur sur le(s) champ(s) : ": errOuts})
    } else {

        db, _ := Database()
        defer db.Close()
        db.Save(&todo)

        c.JSON(http.StatusCreated, gin.H{"status" : http.StatusCreated, "message" : "Todo item created successfully!", "resourceId": todo.ID})
    }
}

//FetchAllTodo récupération de tous les todos
func FetchAllTodo(c *gin.Context) {
    var todos []Todo
    var _todos []TransformedTodo

    db, _ := Database()
    defer db.Close()
    db.Find(&todos)

    if (len(todos) <= 0) {
        c.JSON(http.StatusNotFound, gin.H{"status" : http.StatusNotFound, "message" : "No todo found!"})
        return
    }

    //transforms the todos for building a good response,
    //je peux choisir des champs a ne pas display
    for _, item := range todos {
        status := false
        if (item.Status == 1) {
            status = true
        } else {
            status = false
        }
        _todos = append(_todos, TransformedTodo{ID: item.ID, URL:item.URL})
    }
    c.JSON(http.StatusOK, gin.H{"status" : http.StatusOK, "data" : _todos})
}

//FetchSingleTodo Récupération d'un seul todo en fonction de son id
func FetchSingleTodo(c *gin.Context) {
    var todo Todo
    todoID := c.Param("id")

    db, _ := Database()
    defer db.Close()
    db.First(&todo, todoID)

    if (todo.ID == 0) {
        c.JSON(http.StatusNotFound, gin.H{"status" : http.StatusNotFound, "message" : "No todo found!"})
        return
    }

    _todo := TransformedTodo{ID: todo.ID, URL:todo.URL}
    c.JSON(http.StatusOK, gin.H{"status" : http.StatusOK, "data" : _todo})
}

//UpdateTodo Mise à jour d'un todo
func UpdateTodo(c *gin.Context) {
    var todo Todo
    todoID := c.Param("id")
    db, _ := Database()
    defer db.Close()
    db.First(&todo, todoID)

    if (todo.ID == 0) {
        c.JSON(http.StatusNotFound, gin.H{"status" : http.StatusNotFound, "message" : "No todo found!"})
        return
    }

    db.Model(&todo).Update("title", c.PostForm("title"))
    db.Model(&todo).Update("completed", c.PostForm("completed"))
    c.JSON(http.StatusOK, gin.H{"status" : http.StatusOK, "message" : "Todo updated successfully!"})
}


//DeleteTodo Suppression d'un todo
func DeleteTodo(c *gin.Context) {
    var todo Todo
    todoID := c.Param("id")
    db, _ := Database()
    defer db.Close()
    db.First(&todo, todoID)

    if (todo.ID == 0) {
        c.JSON(http.StatusNotFound, gin.H{"status" : http.StatusNotFound, "message" : "No todo found!"})
        return
    }

    db.Delete(&todo)
    c.JSON(http.StatusOK, gin.H{"status" : http.StatusOK, "message" : "Todo deleted successfully!"})
}

The Idea is to have a xxxxCRUD.go file for each entity to handle but the whole folder in the same package.

the exact errror is :

PS D:\www\developpement> go run .\maincode.go [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode)

panic: runtime error: invalid memory address or nil pointer dereference [signal 0xc0000005 code=0x0 addr=0x0 pc=0x46cc0f]

goroutine 1 [running]: panic(0x831880, 0xc04200a080) C:/Go/src/runtime/panic.go:500 +0x1af /D/www/developpement/apirest.LoadTodo() D:/www/developpement/apirest/todoCRUD.go:33 +0x2f [Router.Group] /D/www/developpement/apirest.init.1() D:/www/developpement/apirest/apirest.go:73 +0x220 [LoadTodo()] /D/www/developpement/apirest.init() D:/www/developpement/apirest/todoCRUD.go:190 +0x80 [last line] main.init() D:/www/developpement/maincode.go:13 +0x3a [manners.ListenAndServe(":8080", apirest.Router)] exit status 2

I hope that this will help to understand !

Thanks for your time and help !

Stéphane

解决方案

I did manage to make it work by "sending" the router in the LoadTodo function :

in apirest.go :

LoadTodo(Router)

and in todoCRUD.go :

func LoadTodo(r *gin.Engine){

and it's working fine ... I hope I didn't bring a bug failure in the code ...

Stéphane

这篇关于golang gin-gonic和包装文件拆分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆