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 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况
  • ¥15 画两个图 python或R
  • ¥15 在线请求openmv与pixhawk 实现实时目标跟踪的具体通讯方法
  • ¥15 八路抢答器设计出现故障
  • ¥15 请教一下c语言的代码里有一个地方不懂
  • ¥15 opencv 无法读取视频
  • ¥15 用matlab 实现通信仿真
  • ¥15 按键修改电子时钟,C51单片机
  • ¥60 Java中实现如何实现张量类,并用于图像处理(不运用其他科学计算库和图像处理库))
  • ¥20 5037端口被adb自己占了