Created
May 28, 2025 03:55
-
-
Save ScaferuZ/2de9b71efc227e359ec7ddc8f318b864 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"database/sql" | |
"fmt" | |
"html/template" | |
"log" | |
"net/http" | |
"os" | |
_ "github.com/lib/pq" | |
) | |
type Counter struct { | |
ID int `json:"id"` | |
Count int `json:"count"` | |
} | |
var db *sql.DB | |
var tmpl *template.Template | |
func main() { | |
// Initialize database connection | |
initDB() | |
// Initialize template | |
tmpl = template.Must(template.ParseGlob("templates/*.html")) | |
// Routes | |
http.HandleFunc("/", homeHandler) | |
http.HandleFunc("/increment", incrementHandler) | |
http.HandleFunc("/decrement", decrementHandler) | |
http.HandleFunc("/reset", resetHandler) | |
http.HandleFunc("/health", healthHandler) | |
port := os.Getenv("PORT") | |
if port == "" { | |
port = "8080" | |
} | |
log.Printf("Server starting on port %s", port) | |
log.Fatal(http.ListenAndServe(":"+port, nil)) | |
} | |
func initDB() { | |
// Database connection string | |
dbHost := os.Getenv("DB_HOST") | |
if dbHost == "" { | |
dbHost = "localhost" | |
} | |
dbUser := os.Getenv("DB_USER") | |
if dbUser == "" { | |
dbUser = "postgres" | |
} | |
dbPassword := os.Getenv("DB_PASSWORD") | |
if dbPassword == "" { | |
dbPassword = "password" | |
} | |
dbName := os.Getenv("DB_NAME") | |
if dbName == "" { | |
dbName = "counter_app" | |
} | |
dbPort := os.Getenv("DB_PORT") | |
if dbPort == "" { | |
dbPort = "5432" | |
} | |
connStr := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", | |
dbHost, dbPort, dbUser, dbPassword, dbName) | |
var err error | |
db, err = sql.Open("postgres", connStr) | |
if err != nil { | |
log.Fatal("Failed to connect to database:", err) | |
} | |
// Test connection | |
if err = db.Ping(); err != nil { | |
log.Fatal("Failed to ping database:", err) | |
} | |
log.Println("Connected to database successfully") | |
// Create table if it doesn't exist | |
createTable() | |
// Initialize counter if it doesn't exist | |
initCounter() | |
} | |
func createTable() { | |
query := ` | |
CREATE TABLE IF NOT EXISTS counters ( | |
id SERIAL PRIMARY KEY, | |
count INTEGER NOT NULL DEFAULT 0 | |
)` | |
_, err := db.Exec(query) | |
if err != nil { | |
log.Fatal("Failed to create table:", err) | |
} | |
log.Println("Table created or already exists") | |
} | |
func initCounter() { | |
var count int | |
err := db.QueryRow("SELECT COUNT(*) FROM counters").Scan(&count) | |
if err != nil { | |
log.Fatal("Failed to check counter:", err) | |
} | |
if count == 0 { | |
_, err = db.Exec("INSERT INTO counters (count) VALUES (0)") | |
if err != nil { | |
log.Fatal("Failed to initialize counter:", err) | |
} | |
log.Println("Counter initialized") | |
} | |
} | |
func getCurrentCount() int { | |
var count int | |
err := db.QueryRow("SELECT count FROM counters WHERE id = 1").Scan(&count) | |
if err != nil { | |
log.Printf("Error getting count: %v", err) | |
return 0 | |
} | |
return count | |
} | |
func updateCount(newCount int) error { | |
_, err := db.Exec("UPDATE counters SET count = $1 WHERE id = 1", newCount) | |
return err | |
} | |
func homeHandler(w http.ResponseWriter, r *http.Request) { | |
count := getCurrentCount() | |
data := Counter{ID: 1, Count: count} | |
err := tmpl.ExecuteTemplate(w, "index.html", data) | |
if err != nil { | |
http.Error(w, err.Error(), http.StatusInternalServerError) | |
return | |
} | |
} | |
func incrementHandler(w http.ResponseWriter, r *http.Request) { | |
if r.Method != "POST" { | |
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) | |
return | |
} | |
currentCount := getCurrentCount() | |
newCount := currentCount + 1 | |
err := updateCount(newCount) | |
if err != nil { | |
http.Error(w, "Failed to update counter", http.StatusInternalServerError) | |
return | |
} | |
http.Redirect(w, r, "/", http.StatusSeeOther) | |
} | |
func decrementHandler(w http.ResponseWriter, r *http.Request) { | |
if r.Method != "POST" { | |
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) | |
return | |
} | |
currentCount := getCurrentCount() | |
newCount := currentCount - 1 | |
err := updateCount(newCount) | |
if err != nil { | |
http.Error(w, "Failed to update counter", http.StatusInternalServerError) | |
return | |
} | |
http.Redirect(w, r, "/", http.StatusSeeOther) | |
} | |
func resetHandler(w http.ResponseWriter, r *http.Request) { | |
if r.Method != "POST" { | |
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) | |
return | |
} | |
err := updateCount(0) | |
if err != nil { | |
http.Error(w, "Failed to reset counter", http.StatusInternalServerError) | |
return | |
} | |
http.Redirect(w, r, "/", http.StatusSeeOther) | |
} | |
func healthHandler(w http.ResponseWriter, r *http.Request) { | |
// Check database connection | |
if err := db.Ping(); err != nil { | |
w.WriteHeader(http.StatusServiceUnavailable) | |
fmt.Fprintf(w, "Database connection failed: %v", err) | |
return | |
} | |
w.WriteHeader(http.StatusOK) | |
fmt.Fprint(w, "OK") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment