2023-11-12 06:42:55 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
|
|
)
|
|
|
|
|
|
|
|
// This is a function that takes a long time to run
|
|
|
|
// Useful for demonstrating concurrency (goroutines)
|
|
|
|
func delayPrint() {
|
|
|
|
time.Sleep(5 * time.Second)
|
|
|
|
fmt.Printf("delay print\n")
|
|
|
|
}
|
|
|
|
|
2024-02-02 16:25:41 +01:00
|
|
|
// Reads files from the migrations directory and runs them
|
|
|
|
func runMigrations(db *sqlx.DB) error {
|
|
|
|
// Read the migrations directory
|
|
|
|
files, err := os.ReadDir("migrations")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run each migration file
|
|
|
|
for _, file := range files {
|
|
|
|
// Skip directories
|
|
|
|
if file.IsDir() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the migration file
|
|
|
|
content, err := os.ReadFile("migrations/" + file.Name())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execute the migration SQL
|
|
|
|
_, err = db.Exec(string(content))
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error executing migration %s: %s\n", file.Name(), err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Printf("Migration %s executed\n", file.Name())
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println("Migrations complete")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-11-12 06:42:55 +01:00
|
|
|
// This is what a handler looks like
|
2024-02-02 16:25:41 +01:00
|
|
|
func handler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
fmt.Println("Request received")
|
|
|
|
go delayPrint() // This will run in the background
|
2023-11-12 06:42:55 +01:00
|
|
|
io.WriteString(w, "This is my website!\n")
|
|
|
|
}
|
|
|
|
|
2024-02-02 16:25:41 +01:00
|
|
|
func dbConnect() *sqlx.DB {
|
2023-11-12 06:42:55 +01:00
|
|
|
// Check for the environment variable
|
|
|
|
dbpath := os.Getenv("SQLITE_DB_PATH")
|
|
|
|
|
|
|
|
// Default to something reasonable
|
|
|
|
if dbpath == "" {
|
|
|
|
dbpath = "./db.sqlite3"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open the database
|
|
|
|
// db, err := sqlx.Connect("sqlite3", ":memory:")
|
|
|
|
db, err := sqlx.Connect("sqlite3", dbpath)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = db.Ping()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2024-02-02 16:25:41 +01:00
|
|
|
// Run the migrations
|
|
|
|
err = runMigrations(db)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return db
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
println("Starting server...")
|
|
|
|
|
|
|
|
// Connect to the database
|
|
|
|
db := dbConnect()
|
|
|
|
defer db.Close()
|
|
|
|
|
|
|
|
// Tx is a transaction
|
|
|
|
tx := db.MustBegin()
|
|
|
|
tx.MustExec("INSERT INTO users (username, password) VALUES (?, ?)", "John Doe", "a")
|
|
|
|
err := tx.Commit()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is how you query the database
|
|
|
|
rows, err := db.Queryx("SELECT * FROM users")
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for rows.Next() {
|
|
|
|
var user struct {
|
|
|
|
ID int
|
|
|
|
Username string
|
|
|
|
Password string
|
|
|
|
}
|
|
|
|
err = rows.StructScan(&user)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
fmt.Printf("User: %d %s %s\n", user.ID, user.Username, user.Password)
|
|
|
|
}
|
2023-11-12 06:42:55 +01:00
|
|
|
|
|
|
|
// Mounting the handler
|
|
|
|
|
|
|
|
fs := http.FileServer(http.Dir("static"))
|
|
|
|
http.Handle("/", fs)
|
2024-02-02 16:25:41 +01:00
|
|
|
http.HandleFunc("/hello", handler)
|
2023-11-12 06:42:55 +01:00
|
|
|
|
|
|
|
// Start the server on port 8080
|
|
|
|
err = http.ListenAndServe(":8080", nil)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|