Skip to content

Instantly share code, notes, and snippets.

@alexedwards
Last active October 17, 2020 21:24
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save alexedwards/8b4b0cd4495d7c3abadd to your computer and use it in GitHub Desktop.
Save alexedwards/8b4b0cd4495d7c3abadd to your computer and use it in GitHub Desktop.
.
├── books
│   ├── handlers.go
│   └── models.go
├── config
│   └── db.go
└── main.go
package config
import (
"database/sql"
_ "github.com/lib/pq"
"log"
)
var DB *sql.DB
func InitDB(dataSourceName string) {
var err error
DB, err = sql.Open("postgres", dataSourceName)
if err != nil {
log.Panic(err)
}
if err = DB.Ping(); err != nil {
log.Panic(err)
}
}
package books
import (
"fmt"
"net/http"
)
func BooksIndex(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
http.Error(w, http.StatusText(405), 405)
return
}
bks, err := AllBooks()
if err != nil {
http.Error(w, http.StatusText(500), 500)
return
}
for _, bk := range bks {
fmt.Fprintf(w, "%s, %s, %s, £%.2f\n", bk.Isbn, bk.Title, bk.Author, bk.Price)
}
}
package main
import (
"bookstore/books"
"bookstore/config"
"net/http"
)
func main() {
config.InitDB("postgres://user:pass@localhost/bookstore")
http.HandleFunc("/books", books.BooksIndex)
http.ListenAndServe(":3000", nil)
}
package books
import "bookstore/config"
type Book struct {
Isbn string
Title string
Author string
Price float32
}
func AllBooks() ([]*Book, error) {
rows, err := config.DB.Query("SELECT * FROM books")
if err != nil {
return nil, err
}
defer rows.Close()
bks := make([]*Book, 0)
for rows.Next() {
bk := new(Book)
err := rows.Scan(&bk.Isbn, &bk.Title, &bk.Author, &bk.Price)
if err != nil {
return nil, err
}
bks = append(bks, bk)
}
if err = rows.Err(); err != nil {
return nil, err
}
return bks, nil
}
@amitt001
Copy link

amitt001 commented May 9, 2017

Isn't import "bookstore/config" creates a completely new import with all values reset?

if yes, how we are able to use db object without initializing in models.go AllBooks() function?

@cqxmzhc
Copy link

cqxmzhc commented May 15, 2017

@amitt001 package initialization is done only once even if package is imported many times.

@filinvadim
Copy link

Bad design. Use DI

@moisoto
Copy link

moisoto commented Jan 27, 2020

Bad design. Use DI

This gist is part of a bigger article which includes Dependency Injection.

https://www.alexedwards.net/blog/organising-database-access

@inliquid
Copy link

@filinvadim import of a package IS DI. And it lets your application correctly utilize Go's composition principles. See recent Gophercon talk by Uber.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment