// sensor state struct type sensorState struct { a float64 b int lock sync.Mutex ch chan int } type curStatus struct { a float64 b int ... } // log struct type stateLog struct { state curStatus timestamp int64 method string } // stateMap maintains state of different sensors var stateMap sync.Map stateMap.Store("Sensor-A", &sensorState{ a : 0, b : 0, lock : sync.Mutex{}, ch : make(chan int) }) func ChargerMonitoringThreadV2(sensorId string) { isStateLocked := false sensorStatus := curStatus{} sessionState, _ := stateMap.Load(sensorId) state, _ := sessionState.(*sensorState) defer func() { if er := recover(); er != nil { fmt.Printf("ERROR: [sensorId:%s][ChargerMonitoringThreadV2] Recovered from - %v", sensorId, er) fmt.Printf("ERROR: [sensorId:%s][ChargerMonitoringThreadV2] stacktrace from panic:\n%s", sensorId, string(debug.Stack())) if isStateLocked { fmt.Printf("INFO: [sensorId:%s][ChargerMonitoringThreadV2] Released lock\n", sensorId) state.lock.Unlock() isStateLocked = false } go ChargerMonitoringThreadV2(sensorId) logging.ReportException(fmt.Errorf("%v\n%s", er, string(debug.Stack()))) // log error return } }() for { select { case <-state.ch: fmt.Printf("INFO: [sensorId:%s][monitoringThread] Terminating monitoring thread...\n", sensorId) return default: curTS := time.Now().UnixMilli() state.lock.Lock() isSessionStateLocked = true sensorStatus.a = state.a state.lock.Unlock() isSessionStateLocked = false insertLog(&stateLog{ state: sensorStatus, timestamp: curTS, method: "monitoringThread", }) time.Sleep(60 * time.Second) } } }