包裹

时间:2017-02-13 16:37:18

标签: rest variables go scope package

我很想去学习,我正在设置一个使用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中的路由器

斯特凡 PS:我确实为包设置了一个子文件夹,如果它在一个文件中,我可以构建它。

我虽然解决方案是将路由器变量声明为* gin.Engine但是在编译正常时,我在Router.Group调用上遇到了恐慌错误

让我发布更多部分代码:

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)
}

然后我将apirest包拆分为2个文件:

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

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()

}

然后处理所有声明的todoCRUD.go文件,todoCRUD.go和apirest.go位于相同的子文件夹apirest(并编译好):

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!"})
}

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

确切的错误是:

  

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

     

恐慌:运行时错误:无效的内存地址或无指针   解引用[信号0xc0000005代码= 0x0 addr = 0x0 pc = 0x46cc0f]

     

goroutine 1 [running]:恐慌(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)]退出状态2

我希望这有助于理解!

感谢您的时间和帮助!

斯特凡

1 个答案:

答案 0 :(得分:1)

我确实通过在LoadTodo函数中“发送”路由器来使其工作:

在apirest.go中:

LoadTodo(Router)

和todoCRUD.go:

func LoadTodo(r *gin.Engine){

并且它工作正常......我希望我没有在代码中带来错误...

斯特凡