Go 封装处理程序代码后出现错误500

Go 封装处理程序代码后出现错误500,go,Go,我继承了其他两位开发人员编写的代码。看来,一个概念验证网站变成了生产代码,所以大部分代码都是主要的。理论上这是一个简单的程序。该设置是一个树莓pi,它控制用go编写的喷水装置,可以设置打开不同区域的时间表。我已经成功地将中继控制器封装到一个包中,现在我想封装ScheduleAPI。该部分是一个相当直接的CRUD操作。为了简单起见,我将在schedule_处理程序中的main和bare basics中发布我调用它的地方。因此,首先: main.go func main() { log.Se

我继承了其他两位开发人员编写的代码。看来,一个概念验证网站变成了生产代码,所以大部分代码都是主要的。理论上这是一个简单的程序。该设置是一个树莓pi,它控制用go编写的喷水装置,可以设置打开不同区域的时间表。我已经成功地将中继控制器封装到一个包中,现在我想封装ScheduleAPI。该部分是一个相当直接的CRUD操作。为了简单起见,我将在schedule_处理程序中的main和bare basics中发布我调用它的地方。因此,首先:

main.go

func main() {
    log.SetFlags(log.LstdFlags | log.LUTC)
    log.SetOutput(&lumberjack.Logger{
        Filename:   "application.log",
        MaxSize:    10, // megabytes
        MaxBackups: 3,
        MaxAge:     365, //days
        LocalTime:  false,
    })
    log.Printf("System Startup\n")

    parseTemplates()
    loadConfig()
    config.Eth0Addr = getIPv4ForInterfaceName("eth0")
    saveConfig()
    log.Printf("local ethernet address: %s\n", config.Eth0Addr)

    // gin.SetMode(gin.ReleaseMode)
    gin.SetMode(gin.DebugMode)
    r := gin.Default()

    r.GET("/", mainGetHandler) // homepage
    r.GET("/login", loginGetHandler)
    r.POST("/login", loginPostHandler)
    r.GET("/logout", authRequired(), logoutGetHandler)

    scheduleRepository = nsScheduleRepository.Default("schedule.json")
    parameters := nsScheduleApi.ScheduleHandlerParameters{
        Engine:     r,
        Repository: scheduleRepository,
    }
    nsScheduleApi.Init(&parameters)
    r.GET("/schedule", authRequired(), scheduleGetHandler)

    http.Handle("/", r)
    r.Static("/static/", "./static/")
    config.URL = ""
    // hack - wait 10 seconds for network to come up...
    time.Sleep(10 * time.Second)
    log.Println("Starting up on port 80")
    log.Fatal(http.ListenAndServe(":80", r))
}
package api

import (
    "mysprinkler/schedule"
    "github.com/gin-gonic/gin"
    "log"
    "strconv"
)

type ScheduleHandlerParameters struct {
    Repository schedule.ScheduleRepository
    Engine     *gin.Engine
}

var parameters *ScheduleHandlerParameters

func getSchedules(c *gin.Context) {
    repository := parameters.Repository
    circuitnum, _ := strconv.ParseInt(c.Query("circuitnum"), 10, 64)
    log.Printf("[ScheduleHandler] getting schedules %d", circuitnum)
    var scheds = make([]*schedule.Schedule2, 0)
    if circuitnum > 0 {
        schedule := repository.Get(string(circuitnum))
        if schedule == nil {
            // c.AbortWithStatus(404)
            log.Printf("[ScheduleHandler] Could not find schedule '%d' in db", circuitnum)
        } else {
            scheds = append(scheds, schedule)
        }
    } else {
        scheds = repository.GetAll()
    }
    c.JSON(200, scheds)
}

func getSchedule(c *gin.Context) {
    repository := parameters.Repository
    id := c.Params.ByName("id")
    log.Printf("[ScheduleHandler] getting schedule %s", id)
    sched := repository.Get(id)
    c.JSON(200, sched)
}

func createSchedule(c *gin.Context) {
    repository := parameters.Repository
    var sched schedule.Schedule2
    err := c.BindJSON(&sched)
    if err != nil {
        log.Printf("[ScheduleHandler] Error creating schedule %s", err)
    } else {
        log.Printf("[ScheduleHandler] insert schedule for circuit %d", sched.CircuitNum)
    }
    err = repository.InsertOrUpdate(&sched)
    if err != nil {
        c.AbortWithError(500, err)
        return
    }
    logSchedule(&sched, "created")
    c.JSON(200, sched)
}

func updateSchedule(c *gin.Context) {
    repository := parameters.Repository
    id := c.Params.ByName("id")
    log.Printf("[ScheduleHandler] updating schedule %s", id)
    sched := repository.Get(id)
    c.BindJSON(&sched)
    err := repository.InsertOrUpdate(sched)
    if err != nil {
        c.AbortWithError(500, err)
        return
    }
    logSchedule(sched, "updated")
    c.JSON(200, sched)
}

func deleteSchedule(c *gin.Context) {
    repository := parameters.Repository
    id := c.Params.ByName("id")
    log.Printf("[ScheduleHandler] deleting schedule %s", id)
    err := repository.Delete(id)
    if err != nil {
        c.Error(err)
        return
    }
    c.JSON(200, gin.H{"id #" + id: "deleted"})
}

func logSchedule(sched *schedule.Schedule2, action string) {
    log.Printf("schedule: %s\n", action)
    log.Printf("***  id: %d\n", sched.ID)
    log.Printf("***  load: %d\n", sched.CircuitNum+1)
    log.Printf("***  on time: %s\n", sched.OnTime)
    log.Printf("***  off time: %s\n", sched.OffTime)
    log.Printf("***  enabled: %v", sched.Enabled)
    log.Printf("***  sun: %v", sched.Sun)
    log.Printf("***  mon: %v", sched.Mon)
    log.Printf("***  tue: %v", sched.Tue)
    log.Printf("***  wed: %v", sched.Wed)
    log.Printf("***  thu: %v", sched.Thu)
    log.Printf("***  fri: %v", sched.Fri)
    log.Printf("***  sat: %v", sched.Sat)
}

// Init creates a handler for the schedule api
func Init(parameters *ScheduleHandlerParameters) {
    parameters = parameters
    r := parameters.Engine
    r.GET("/schedule2", getSchedules)
    r.GET("/schedule2/:id", getSchedule)
    r.POST("/schedule2", createSchedule)
    r.PUT("/schedule2/:id", updateSchedule)
    r.DELETE("/schedule2/:id", deleteSchedule)
}
schedule/api/schedule\u handler.go

func main() {
    log.SetFlags(log.LstdFlags | log.LUTC)
    log.SetOutput(&lumberjack.Logger{
        Filename:   "application.log",
        MaxSize:    10, // megabytes
        MaxBackups: 3,
        MaxAge:     365, //days
        LocalTime:  false,
    })
    log.Printf("System Startup\n")

    parseTemplates()
    loadConfig()
    config.Eth0Addr = getIPv4ForInterfaceName("eth0")
    saveConfig()
    log.Printf("local ethernet address: %s\n", config.Eth0Addr)

    // gin.SetMode(gin.ReleaseMode)
    gin.SetMode(gin.DebugMode)
    r := gin.Default()

    r.GET("/", mainGetHandler) // homepage
    r.GET("/login", loginGetHandler)
    r.POST("/login", loginPostHandler)
    r.GET("/logout", authRequired(), logoutGetHandler)

    scheduleRepository = nsScheduleRepository.Default("schedule.json")
    parameters := nsScheduleApi.ScheduleHandlerParameters{
        Engine:     r,
        Repository: scheduleRepository,
    }
    nsScheduleApi.Init(&parameters)
    r.GET("/schedule", authRequired(), scheduleGetHandler)

    http.Handle("/", r)
    r.Static("/static/", "./static/")
    config.URL = ""
    // hack - wait 10 seconds for network to come up...
    time.Sleep(10 * time.Second)
    log.Println("Starting up on port 80")
    log.Fatal(http.ListenAndServe(":80", r))
}
package api

import (
    "mysprinkler/schedule"
    "github.com/gin-gonic/gin"
    "log"
    "strconv"
)

type ScheduleHandlerParameters struct {
    Repository schedule.ScheduleRepository
    Engine     *gin.Engine
}

var parameters *ScheduleHandlerParameters

func getSchedules(c *gin.Context) {
    repository := parameters.Repository
    circuitnum, _ := strconv.ParseInt(c.Query("circuitnum"), 10, 64)
    log.Printf("[ScheduleHandler] getting schedules %d", circuitnum)
    var scheds = make([]*schedule.Schedule2, 0)
    if circuitnum > 0 {
        schedule := repository.Get(string(circuitnum))
        if schedule == nil {
            // c.AbortWithStatus(404)
            log.Printf("[ScheduleHandler] Could not find schedule '%d' in db", circuitnum)
        } else {
            scheds = append(scheds, schedule)
        }
    } else {
        scheds = repository.GetAll()
    }
    c.JSON(200, scheds)
}

func getSchedule(c *gin.Context) {
    repository := parameters.Repository
    id := c.Params.ByName("id")
    log.Printf("[ScheduleHandler] getting schedule %s", id)
    sched := repository.Get(id)
    c.JSON(200, sched)
}

func createSchedule(c *gin.Context) {
    repository := parameters.Repository
    var sched schedule.Schedule2
    err := c.BindJSON(&sched)
    if err != nil {
        log.Printf("[ScheduleHandler] Error creating schedule %s", err)
    } else {
        log.Printf("[ScheduleHandler] insert schedule for circuit %d", sched.CircuitNum)
    }
    err = repository.InsertOrUpdate(&sched)
    if err != nil {
        c.AbortWithError(500, err)
        return
    }
    logSchedule(&sched, "created")
    c.JSON(200, sched)
}

func updateSchedule(c *gin.Context) {
    repository := parameters.Repository
    id := c.Params.ByName("id")
    log.Printf("[ScheduleHandler] updating schedule %s", id)
    sched := repository.Get(id)
    c.BindJSON(&sched)
    err := repository.InsertOrUpdate(sched)
    if err != nil {
        c.AbortWithError(500, err)
        return
    }
    logSchedule(sched, "updated")
    c.JSON(200, sched)
}

func deleteSchedule(c *gin.Context) {
    repository := parameters.Repository
    id := c.Params.ByName("id")
    log.Printf("[ScheduleHandler] deleting schedule %s", id)
    err := repository.Delete(id)
    if err != nil {
        c.Error(err)
        return
    }
    c.JSON(200, gin.H{"id #" + id: "deleted"})
}

func logSchedule(sched *schedule.Schedule2, action string) {
    log.Printf("schedule: %s\n", action)
    log.Printf("***  id: %d\n", sched.ID)
    log.Printf("***  load: %d\n", sched.CircuitNum+1)
    log.Printf("***  on time: %s\n", sched.OnTime)
    log.Printf("***  off time: %s\n", sched.OffTime)
    log.Printf("***  enabled: %v", sched.Enabled)
    log.Printf("***  sun: %v", sched.Sun)
    log.Printf("***  mon: %v", sched.Mon)
    log.Printf("***  tue: %v", sched.Tue)
    log.Printf("***  wed: %v", sched.Wed)
    log.Printf("***  thu: %v", sched.Thu)
    log.Printf("***  fri: %v", sched.Fri)
    log.Printf("***  sat: %v", sched.Sat)
}

// Init creates a handler for the schedule api
func Init(parameters *ScheduleHandlerParameters) {
    parameters = parameters
    r := parameters.Engine
    r.GET("/schedule2", getSchedules)
    r.GET("/schedule2/:id", getSchedule)
    r.POST("/schedule2", createSchedule)
    r.PUT("/schedule2/:id", updateSchedule)
    r.DELETE("/schedule2/:id", deleteSchedule)
}
在我看到的日志中

2018/05/20 12:14:36 System Startup
2018/05/20 12:14:36 local ethernet address: 10.0.0.7
2018/05/20 12:14:36 [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)

2018/05/20 12:14:36 [GIN-debug] GET    /                         --> main.mainGetHandler (3 handlers)
2018/05/20 12:14:36 [GIN-debug] GET    /login                    --> main.loginGetHandler (3 handlers)
2018/05/20 12:14:36 [GIN-debug] POST   /login                    --> main.loginPostHandler (3 handlers)
2018/05/20 12:14:36 [GIN-debug] GET    /logout                   --> main.logoutGetHandler (4 handlers)
2018/05/20 12:14:36 [GIN-debug] GET    /schedule2                --> sprinkler/schedule/api.getSchedules (3 handlers)
2018/05/20 12:14:36 [GIN-debug] GET    /schedule2/:id            --> sprinkler/schedule/api.getSchedule (3 handlers)
2018/05/20 12:14:36 [GIN-debug] POST   /schedule2                --> sprinkler/schedule/api.createSchedule (3 handlers)
2018/05/20 12:14:36 [GIN-debug] PUT    /schedule2/:id            --> sprinkler/schedule/api.updateSchedule (3 handlers)
2018/05/20 12:14:36 [GIN-debug] DELETE /schedule2/:id            --> sprinkler/schedule/api.deleteSchedule (3 handlers)
2018/05/20 12:14:36 [GIN-debug] GET    /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers)
2018/05/20 12:14:36 [GIN-debug] HEAD   /static/*filepath         --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers)
2018/05/20 12:14:46 Starting up on port 80
2018/05/20 12:15:15 admin logged in

但是当我导航到/schedule2时,模板被加载,然后立即得到两个内部500错误(每个调用/schedule2?circuitnum=1都有一个)。现在,这段代码以前可以工作了,当它在主程序中时,我只是将这些方法移动到schedule_api文件中,然后制作一个
Init
,并将设置代码放入其中。有了C#背景,我不明白为什么会这样。我的第一个猜测是,当调度处理程序退出
Main
的范围时,我丢失了对它的引用,但我不明白为什么。知道我哪里出错了吗

没错!进行此操作时:

func Init(parameters *ScheduleHandlerParameters) {
    parameters = parameters
    // ....
}
参数
成为此函数的局部变量,下一行只是将其分配给自身。全局变量
参数
仍然保持
nil
值,从未更改。这导致了错误

将函数param更改为类似以下内容应该可以正常工作:

func Init(shPrms *ScheduleHandlerParameters) {
    parameters = shPrms
    // ....
}

我想我明白了。我必须测试以确定,但看起来init中的自我分配搞砸了。我将init上的参数重命名为不同的名称,它现在似乎可以工作了:我想您会后悔在这里使用全局变量。@bohdan_trotsenko我一直怀疑是否使用它。我还是个新手。什么是更好的练习?创建一个非导出结构来保存我的值?我建议使用一个带有参数的公共结构,只需删除全局变量。将函数更新为
*api.ScheduleHandlerParameters
上的方法;(这是最起码的;您可以更新或使用一组不同的结构/方法)