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
        // ....
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 ensp启动设备蓝屏,代码clock_watchdog_timeout
  • ¥15 Android studio AVD启动不了
  • ¥15 陆空双模式无人机怎么做
  • ¥15 想咨询点问题,与算法转换,负荷预测,数字孪生有关
  • ¥15 C#中的编译平台的区别影响
  • ¥15 软件供应链安全是跟可靠性有关还是跟安全性有关?
  • ¥15 电脑蓝屏logfilessrtsrttrail问题
  • ¥20 关于wordpress建站遇到的问题!(语言-php)(相关搜索:云服务器)
  • ¥15 【求职】怎么找到一个周围人素质都很高不会欺负他人,并且未来月薪能够达到一万以上(技术岗)的工作?希望可以收到写有具体,可靠,已经实践过了的路径的回答?
  • ¥15 Java+vue部署版本反编译