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 keil的map文件中Image component sizes各项意思
  • ¥30 BC260Y用MQTT向阿里云发布主题消息一直错误
  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)