doudi8519 2018-05-20 13:49 采纳率: 100%
浏览 75
已采纳

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

I've inherited code that was done by 2 other developers. It appears that a proof of concept website turned into production code so most all of the code is in main. It's a simple program in theory. The setup is a raspberry pi that controls sprinklers written in go that can set a schedule of turning on different zones. I've successfully encapsulated the relay controller into a package, now I want to encapsulate the schedule api. The part is a fairly straight forward CRUD operations.for simplicity I'll just post where I call it from main and the bare basics in the schedule_handler. so first:

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

    parseTemplates()
    loadConfig()
    config.Eth0Addr = getIPv4ForInterfaceName("eth0")
    saveConfig()
    log.Printf("local ethernet address: %s
", 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))
}

schedule/api/schedule_handler.go

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
", action)
    log.Printf("***  id: %d
", sched.ID)
    log.Printf("***  load: %d
", sched.CircuitNum+1)
    log.Printf("***  on time: %s
", sched.OnTime)
    log.Printf("***  off time: %s
", 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)
}

In the log I'm seeing

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

but when I navigate to /schedule the template is loaded then immediatly i get two internal 500 errors (one for each call to /schedule2?circuitnum=1). Now this code worked before when it was all in main i just moved the methods into the schedule_api file then made an Init and put that setup code into it. Having a C# background I'm lost as to why this broke. My first guess is that I'm losing a reference to my schedule handler when it drops out of scope of Main but I don't understand why. Any ideas where I went wrong?

  • 写回答

1条回答 默认 最新

  • dongshou6041 2018-05-21 09:10
    关注

    Exactly! When you are doing this:

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

    parameters becomes a local variable to this function and next line is just assigning it to itself. And global variable parameters still holds nil value, was never changed. Which caused error!

    Changing function param to something like this should work fine:

    func Init(shPrms *ScheduleHandlerParameters) {
        parameters = shPrms
        // ....
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

    报告相同问题?

    悬赏问题

    • ¥15 这个要用一维热方程但是我不知道怎么运用这个公式
    • ¥15 OpenFOAM多孔介质传热模型建模
    • ¥15 QT 实现 RSTP 语音对讲功能
    • ¥50 AES魔改之后的安全性关于PRF(相关搜索:密码学)
    • ¥15 用C语言写的一个程序遇到了两个问题第一是偏移正确但读取不到坐标,第二个问题是自己定义的函数实现不了获取指定进程模块。
    • ¥15 在安装Anaconda时总是闪退怎么办?
    • ¥15 对图中电路进行以下几个方面的分析
    • ¥15 对图中电路进行以下几个方面的分析
    • ¥15 对图中电路进行以下几个方面的分析
    • ¥15 对图中电路进行以下几个方面的分析