Skip to content

Instantly share code, notes, and snippets.

@alochym01
Created August 26, 2021 15:23
Show Gist options
  • Save alochym01/8170f5b101dec6b51c05a6073004a5db to your computer and use it in GitHub Desktop.
Save alochym01/8170f5b101dec6b51c05a6073004a5db to your computer and use it in GitHub Desktop.
Create a simple Pagination - golang programming
package main
import (
"database/sql"
"encoding/json"
"flag"
"fmt"
"log"
"net/http"
"os"
"strconv"
"github.com/bmizerany/pat"
_ "github.com/mattn/go-sqlite3"
)
// DB connection
var DB *sql.DB
func main() {
var err error
// Define a new command-line flag with the name 'addr', a default value of ":4000"
// and some short help text explaining what the flag controls. The value of the
// flag will be stored in the addr variable at runtime.
addr := flag.String("addr", ":8080", "HTTP network address")
// Use log.New() to create a logger for writing information messages. This takes
// three parameters: the destination to write the logs to (os.Stdout), a string
// prefix for message (INFO followed by a tab), and flags to indicate what
// additional information to include (local date and time). Note that the flags
// are joined using the bitwise OR operator |.
// InfoLog = log.New(os.Stdout, "INFO\t", log.Ldate|log.Ltime|log.Lshortfile)
infoLog := log.New(os.Stdout, "INFO\t", log.Ldate|log.Ltime|log.Llongfile)
// Create a logger for writing error messages in the same way, but use stderr as
// the destination and use the log.Lshortfile flag to include the relevant
// file name and line number.
errLog := log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Llongfile)
mux := pat.New()
// userHandler
// mux.Get("/user", http.HandlerFunc(user.Get))
mux.Get("/user/create", http.HandlerFunc(CreateUser))
mux.Get("/user", http.HandlerFunc(GetUser))
// Importantly, we use the flag.Parse() function to parse the command-line flag.
// This reads in the command-line flag value and assigns it to the addr
// variable. You need to call this *before* you use the addr variable
// otherwise it will always contain the default value of ":4000". If any errors are
// encountered during parsing the application will be terminated.
flag.Parse()
// sqlite
DB, err = sql.Open("sqlite3", "alochym.db")
if err != nil {
panic(err)
}
defer DB.Close()
infoLog.Println("starting server on", *addr)
err = http.ListenAndServe(*addr, mux)
errLog.Fatal(err)
}
// User models
type User struct {
ID int
Name string
Email string
Password string
}
// Pagination Object
type Pagination struct {
Next int
Previous int
RecordPerPage int
CurrentPage int
TotalPage int
}
// Get all User accounts
func (u User) Get(page int) (interface{}, error) {
var (
// Create empty Album
record = User{}
// Create empty slice Album
users = []User{}
data = map[string]interface{}{}
)
limit := 10
offset := limit * (page - 1)
data["Page"] = *pagination("users", limit, page)
// sqlstmt - Avoid SQL Injection Attack
// Using limit and offset to get records
sqlstmt := fmt.Sprintf("SELECT id, name, email FROM users order by id desc limit %d offset %d", limit, offset)
fmt.Println(sqlstmt)
rows, _ := DB.Query(sqlstmt)
// close rows query
defer rows.Close()
for rows.Next() {
err := rows.Scan(&record.ID, &record.Name, &record.Email)
if err != nil {
// check server err
return nil, err
}
// append record to albums slice
users = append(users, record)
}
data["Records"] = users
return data, nil
}
// GetUser return all user records
func GetUser(w http.ResponseWriter, r *http.Request) {
u := User{}
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
if page == 0 {
page = 1
}
result, _ := u.Get(page)
w.Header().Set("Content-Type", "application/json")
// Transform to JSON response
json.NewEncoder(w).Encode(result)
}
// CreateUser mock data
func CreateUser(w http.ResponseWriter, r *http.Request) {
sqldroptable := fmt.Sprint("DROP TABLE users;")
DB.Exec(sqldroptable)
sqltable := fmt.Sprintf("CREATE TABLE users (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, password CHAR(60) NOT NULL, created datetime default current_timestamp)")
// Execute SQL Statements
_, err := DB.Exec(sqltable)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println("User table created")
var users = []User{
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
{Name: "Alice Jones", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Nguyen Ha", Email: "[email protected]", Password: "alochym@123"},
{Name: "Ngo Thi To Nhu", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Hiep", Email: "[email protected]", Password: "alochym@123"},
{Name: "Do Thi Kim Hoa", Email: "[email protected]", Password: "alochym@123"},
}
for _, v := range users {
sqlstmt := fmt.Sprintf("INSERT INTO users(name, email, password) VALUES(\"%s\", \"%s\", \"%s\")",
v.Name,
v.Email,
v.Password,
)
DB.Exec(sqlstmt)
}
w.Write([]byte("Get All Snippet"))
}
// sqlHelper
// running sql command and return error
func sqlHelper(db *sql.DB, sqlstmt string) error {
// Execute SQL Statements
fmt.Println(sqlstmt)
result, err := db.Exec(sqlstmt)
// err check for DB operation
if err != nil {
return err
}
rowCount, err := result.RowsAffected()
// error check for RowsAffected function
if err != nil {
return err
}
// there is no row found
if rowCount == 0 {
return sql.ErrNoRows
}
return nil
}
// Generated Pagination Meta data
func pagination(table string, limit, page int) *Pagination {
var (
tmpl = Pagination{}
recordcount int
)
// Count all record
sqltable := fmt.Sprintf("SELECT count(id) FROM %s", table)
DB.QueryRow(sqltable).Scan(&recordcount)
total := (recordcount / limit)
// Calculator Total Page
remainder := (recordcount % limit)
if remainder == 0 {
tmpl.TotalPage = total
} else {
tmpl.TotalPage = total + 1
}
// Set current/record per page meta data
tmpl.CurrentPage = page
tmpl.RecordPerPage = limit
// Calculator the Next/Previous Page
if page <= 0 {
tmpl.Next = page + 1
} else if page < tmpl.TotalPage {
tmpl.Previous = page - 1
tmpl.Next = page + 1
} else if page == tmpl.TotalPage {
tmpl.Previous = page - 1
tmpl.Next = 0
}
return &tmpl
}
@ehsansouri23
Copy link

you are running count query every time. It is not performance optimized.

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