diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..4931408
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,5 @@
+module git.dm1sh.ru/dm1sh/gotemptracker
+
+go 1.19
+
+require github.com/lib/pq v1.10.7
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..e9190c6
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
+github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
diff --git a/index.gohtml b/index.gohtml
new file mode 100644
index 0000000..546b272
--- /dev/null
+++ b/index.gohtml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+ gotemptracker
+
+
+
+ This is the first step to quantified selt, brought in by Golang app with PostgreSQL database
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..a43b082
--- /dev/null
+++ b/main.go
@@ -0,0 +1,66 @@
+package main
+
+import (
+ "html/template"
+ "log"
+ "net/http"
+ "os"
+ "strconv"
+
+ "git.dm1sh.ru/dm1sh/gotemptracker/models"
+)
+
+func getEnv(name, default_val string) string {
+ val := os.Getenv(name)
+
+ if val == "" {
+ return default_val
+ }
+
+ return val
+}
+
+var tmpl *template.Template
+
+func indexHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method == http.MethodPost {
+ strvalue := r.FormValue("value")
+
+ value, err := strconv.ParseFloat(strvalue, 32)
+ if err != nil {
+ http.Error(w, "Expected floating point value", http.StatusBadRequest)
+ }
+
+ models.InsertMeasurement(value)
+ }
+
+ measurements, err := models.AllMeasurements()
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ err = tmpl.Execute(w, measurements)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func main() {
+ tmpl = template.Must(template.ParseFiles("index.gohtml"))
+
+ err := models.InitDB(getEnv("DB_CONNECTION_STRING", "postgres://gotemptracker:gotemptracker@localhost:5432/gotemptracker?sslmode=disable"))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ http.HandleFunc("/", indexHandler)
+
+ port := getEnv("PORT", "80")
+
+ log.Printf("Listening on %s\n", port)
+
+ if err := http.ListenAndServe(":"+port, nil); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/models/models.go b/models/models.go
new file mode 100644
index 0000000..e27ed67
--- /dev/null
+++ b/models/models.go
@@ -0,0 +1,66 @@
+package models
+
+import (
+ "database/sql"
+ "time"
+
+ _ "github.com/lib/pq"
+)
+
+var db *sql.DB
+
+type Measurement struct {
+ CreatedAt time.Time
+ Value float32
+}
+
+func InitDB(dataSourceName string) (err error) {
+ db, err = sql.Open("postgres", dataSourceName)
+ if err != nil {
+ return err
+ }
+
+ if err = db.Ping(); err != nil {
+ return err
+ }
+
+ _, err = db.Exec(`
+ CREATE TABLE IF NOT EXISTS measurements (
+ created_at TIMESTAMP,
+ value NUMERIC (3, 1)
+ )
+ `)
+ return err
+}
+
+func AllMeasurements() (measurements []Measurement, err error) {
+ rows, err := db.Query("SELECT * FROM measurements")
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ for rows.Next() {
+ var measurement Measurement
+
+ err = rows.Scan(&measurement.CreatedAt, &measurement.Value)
+ if err != nil {
+ return nil, err
+ }
+
+ measurements = append(measurements, measurement)
+ }
+ if err = rows.Err(); err != nil {
+ return nil, err
+ }
+
+ return measurements, nil
+}
+
+func InsertMeasurement(value float64) (err error) {
+ _, err = db.Exec(`
+ INSERT INTO measurements VALUES (current_timestamp, $1)
+ `, value)
+
+ return err
+}