#guys help some error i cant figure it out..
30 messages · Page 1 of 1 (latest)
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
// APIServer represents the JSON API server.
type APIServer struct {
listenAddr string
store Storage
}
// newAPIServer creates a new instance of APIServer with the specified listen address.
func newAPIServer(listenAddr string, store Storage) *APIServer {
return &APIServer{
listenAddr: listenAddr,
store: store,
}
}
// Run starts the JSON API server.
func (s *APIServer) Run() {
router := mux.NewRouter()
// Define routes and link them to corresponding handler functions.
router.HandleFunc("/account", makeHTTPHandleFunc(s.handleAccount))
router.HandleFunc("/account/{id}", makeHTTPHandleFunc(s.handleGetAccountByID))
router.HandleFunc("/account", makeHTTPHandleFunc(s.handleCreateAccount))
router.HandleFunc("/account", makeHTTPHandleFunc(s.handleDeleteAccount))
router.HandleFunc("/account/transfer", makeHTTPHandleFunc(s.handleTransferAccount))
log.Println("JSON API server running on port: ", s.listenAddr)
//start the server
http.ListenAndServe(s.listenAddr, router)
}
// handleAccount handles requests to /account endpoint.
func (s *APIServer) handleAccount(w http.ResponseWriter, r *http.Request) error {
// Handle different HTTP methods for /account endpoint.
switch r.Method {
case "GET":
return s.handleGetAccount(w, r)
case "POST":
return s.handleCreateAccount(w, r)
case "DELETE":
return s.handleDeleteAccount(w, r)
default:
return fmt.Errorf("method not allowed: %s", r.Method)
}
}
func (s *APIServer) handleGetAccount(w http.ResponseWriter, r *http.Request) error {
accounts, err := s.store.GetAccounts()
if err != nil {
return err
}
return WriteJSON(w, http.StatusOK, accounts)
}```
// handleGetAccount handles GET requests to /account endpoint.
func (s *APIServer) handleGetAccountByID(w http.ResponseWriter, r *http.Request) error {
//handle GET request to get specific acc info
id := mux.Vars(r)["id"]
fmt.Println(id)
return WriteJSON(w, http.StatusOK, &Account{})
}
// handleCreateAccount handles POST requests to /account endpoint.
func (s *APIServer) handleCreateAccount(w http.ResponseWriter, r *http.Request) error {
//handle POST request to create new acc
CreateAccountReq := new(CreateAccountRequest)
if err := json.NewDecoder(r.Body).Decode(CreateAccountReq); err != nil {
return err
}
account := NewAccount(CreateAccountReq.FirstName, CreateAccountReq.LastName)
if err := s.store.CreateAccount(account); err != nil {
return err
}
return WriteJSON(w, http.StatusOK, account)
}
// handleDeleteAccount handles DELETE requests to /account endpoint.
func (s *APIServer) handleDeleteAccount(w http.ResponseWriter, r *http.Request) error {
//handle DELETE request to delete an acc
return nil
}
// handleTransferAccount handles POST requests to /account/transfer endpoint.
func (s *APIServer) handleTransferAccount(w http.ResponseWriter, r *http.Request) error {
//handle POST request to transfer func btw accounts
return nil
}
// writes JSON response to the http.ResponseWriter with the specified status code.
func WriteJSON(w http.ResponseWriter, status int, v any) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
return json.NewEncoder(w).Encode(v)
}
// apiFunc is a function signature for handler functions.
type apiFunc func(http.ResponseWriter, *http.Request) error
// ApiError represents the structure for API error responses.
type ApiError struct {
Error string
}
// makeHTTPHandleFunc is a decorator to convert an apiFunc to an http.HandlerFunc
func makeHTTPHandleFunc(f apiFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := f(w, r); err != nil {
WriteJSON(w, http.StatusBadRequest, ApiError{Error: err.Error()})
}
}
}
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
// Storage interface defines methods for interacting with a storage system.
type Storage interface {
CreateAccount(*Account) error
DeleteAccount(int) error
UpdateAccount(*Account) error
GetAccounts() ([]*Account, error)
GetAccountByID(int) (*Account, error)
}
// PostgresStore is a struct representing a PostgreSQL database store.
type PostgresStore struct {
db *sql.DB
}
// NewPostgresStore creates a new instance of PostgresStore and initializes the database connection.
func NewPostgresStore() (*PostgresStore, error) {
connStr := "user=postgres dbname=postgres password=kanjk2340 sslmode=disable"
db, err := sql.Open("postgres", connStr)
if err != nil {
return nil, err
}
if err := db.Ping(); err != nil {
return nil, err
}
return &PostgresStore{
db: db,
}, nil
}
// Init initializes the PostgreSQL database by creating the account table.
func (s *PostgresStore) Init() error {
return s.CreateAccountTable()
}
// CreateAccountTable creates the account table if it does not exist already.
func (s *PostgresStore) CreateAccountTable() error {
query := `CREATE TABLE if not exists account (
id serial primary key,
first_name varchar(50),
last_name varchar(50),
number serial,
balance serial,
created_at timestamp
)`
_, err := s.db.Exec(query)
return err
}```
// CreateAccount creates a new account in the PostgreSQL database.
func (s *PostgresStore) CreateAccount(acc *Account) error {
query := `INSERT INTO account
(first_name, last_name, number, balance, created_at)
VALUES ($1, $2, $3, $4, $5)`
resp, err := s.db.Query(
query,
acc.FirstName,
acc.LastName,
acc.Number,
acc.Balance,
acc.CreatedAt,
)
if err != nil {
return err
}
fmt.Printf("%+v\n", resp)
return nil
}
// UpdateAccount updates an existing account in the PostgreSQL database.
func (s *PostgresStore) UpdateAccount(*Account) error {
return nil
}
// DeleteAccount deletes an account from the PostgreSQL database based on the given ID.
func (s *PostgresStore) DeleteAccount(id int) error {
return nil
}
// GetAccountByID retrieves an account from the PostgreSQL database based on the given ID.
func (s *PostgresStore) GetAccountByID(id int) (*Account, error) {
return nil, nil
}
func (s *PostgresStore) GetAccounts() ([]*Account, error) {
rows, err := s.db.Query("select * from account")
if err != nil {
return nil, err
}
accounts := []*Account{}
for rows.Next() {
account := new(Account)
err := rows.Scan(
&account.ID,
&account.FirstName,
&account.LastName,
&account.Number,
&account.Balance,
&account.CreatedAt)
if err != nil {
return nil, err
}
accounts = append(accounts, account)
}
return accounts, nil
}```
you are tring to scan a nullable colume to a time.Time
you should use sql.NullTime instead
btw select * is not recommend, because you won't know what will happen after the table is changed
oh i was watching a tutoial and it worked for him. i changed to sql.NullTime. so what should i add to time.Now().UTC() ? its showing err
alr, I see, but created_at should never be NULL, so maybe you have to fix your table declaration
created_at is time.Time
"Error": "sql: expected 0 destination arguments in Scan, not 6"
}``` now showing this
I mean the sql table declaration
not your go structure
what is wrong with my table creation? i have been looking into it all these time. searched stackover flow too still couldnt find it...
```query := CREATE TABLE IF NOT EXISTS account ( id SERIAL PRIMARY KEY, first_name VARCHAR(100), last_name VARCHAR(100), number SERIAL, balance SERIAL, created_at TIMESTAMP )
i saw this but i checked out other repo and it was not doing NOTNULL and it worked. on stackover flow too
yes, they works because they checked their code over and over again in their mind. You can do that as well, but if you can't, you have to add these limits to your table then you don't make mistakes
```query := CREATE TABLE IF NOT EXISTS account ( id SERIAL PRIMARY KEY, first_name VARCHAR(100) NOT NULL, last_name VARCHAR(100) NOT NULL, number SERIAL, balance SERIAL, created_at TIMESTAMP NOT NULL )
you have to delete the old table before you can create a new one
makesure your table created successfully by remove the IF NOT EXISTS condition
hey it worked!
thanks a tons tons!!!!
i was spending hours on this and was sooo tired. the error occured because i didnt delete the tables and kept tryijng on it
If your question has been solved, please close the thread with </solved:1022173889255706726>
hey but its still not givin the names as output on postman
i solved it!!!