当前位置:网站首页>Building crud applications in golang
Building crud applications in golang
2022-06-27 12:02:00 【Hua Weiyun】
In this tutorial , We will be in Golang Build a CRUD Applications . We will use gorilla/mux Ku as api and PostgreSQL DB To store data .
stay $GOPATH Create a new project directory go-postgres.
stay go-postgres Open the terminal in the project . Instantiation go modular .
go mod init go-postgresInstallation dependency
We will use... In this project 3 A package , stay go-postgres Open the terminal in the project .
1. gorilla/mux router
gorilla/mux Packet implements a request router and scheduler , Used to match incoming requests to their respective handlers .
go get -u github.com/gorilla/mux2. lib/pq driver
Go Of database/sql Purity of package Go postgres The driver .
go get github.com/lib/pq We will use godotenv Package to read .env file . .env File to save environment variables . Environment variables are used to protect the security of sensitive data .
go get github.com/joho/godotenv Now? , open go.mod And check . All installed dependencies list the installed versions .
A similar , Versions can be different .
module go-postgresrequire ( github.com/gorilla/mux v1.7.4 github.com/joho/godotenv v1.3.0 github.com/lib/pq v1.3.0)install Postgres
PostgreSQL Is a powerful open source object relational database system . It is based on reliability 、 Known for functional robustness and performance .
After creating the instance . Now? , We have to create a table . go to ElephantSQL Medium Browser Tab and paste the following create table query and execute it . We use SERIAL Type as user ID. SERIAL Each insert is incremented automatically .
CREATE TABLE users ( userid SERIAL PRIMARY KEY, name TEXT, age INT, location TEXT);Project directory structure
The project is divided into 4 Parts of , To keep the code modular and clean .
The directory structure is :
|- go-postgres |- middleware |- handlers.go |- models |- models.go |- router |- router.go |- .env |- main.goModel
The model package will store the database schema . We will use struct Type to represent or map golang Database schema in .
stay go-postgres Create a new folder model in the project .
Create a new file in the model models.go And paste the following code .
package models// User schema of the user tabletype User struct { ID int64 `json:"id"` Name string `json:"name"` Location string `json:"location"` Age int64 `json:"age"`}User The structure is what we created above users Representation of tables .
middleware
The middleware package is API And database . This package will handle all database operations , If inserted 、 choice 、 Update and delete (CRUD).
Create a new folder middleware And create a new file in it handlers.go.
Paste the following code .
package middlewareimport ( "database/sql" "encoding/json" // package to encode and decode the json into struct and vice versa "fmt" "go-postgres/models" // models package where User schema is defined "log" "net/http" // used to access the request and response object of the api "os" // used to read the environment variable "strconv" // package used to covert string into int type "github.com/gorilla/mux" // used to get the params from the route "github.com/joho/godotenv" // package used to read the .env file _ "github.com/lib/pq" // postgres golang driver)// response formattype response struct { ID int64 `json:"id,omitempty"` Message string `json:"message,omitempty"`}// create connection with postgres dbfunc createConnection() *sql.DB { // load .env file err := godotenv.Load(".env") if err != nil { log.Fatalf("Error loading .env file") } // Open the connection db, err := sql.Open("postgres", os.Getenv("POSTGRES_URL")) if err != nil { panic(err) } // check the connection err = db.Ping() if err != nil { panic(err) } fmt.Println("Successfully connected!") // return the connection return db}// CreateUser create a user in the postgres dbfunc CreateUser(w http.ResponseWriter, r *http.Request) { // set the header to content type x-www-form-urlencoded // Allow all origin to handle cors issue w.Header().Set("Context-Type", "application/x-www-form-urlencoded") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "POST") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") // create an empty user of type models.User var user models.User // decode the json request to user err := json.NewDecoder(r.Body).Decode(&user) if err != nil { log.Fatalf("Unable to decode the request body. %v", err) } // call insert user function and pass the user insertID := insertUser(user) // format a response object res := response{ ID: insertID, Message: "User created successfully", } // send the response json.NewEncoder(w).Encode(res)}// GetUser will return a single user by its idfunc GetUser(w http.ResponseWriter, r *http.Request) { w.Header().Set("Context-Type", "application/x-www-form-urlencoded") w.Header().Set("Access-Control-Allow-Origin", "*") // get the userid from the request params, key is "id" params := mux.Vars(r) // convert the id type from string to int id, err := strconv.Atoi(params["id"]) if err != nil { log.Fatalf("Unable to convert the string into int. %v", err) } // call the getUser function with user id to retrieve a single user user, err := getUser(int64(id)) if err != nil { log.Fatalf("Unable to get user. %v", err) } // send the response json.NewEncoder(w).Encode(user)}// GetAllUser will return all the usersfunc GetAllUser(w http.ResponseWriter, r *http.Request) { w.Header().Set("Context-Type", "application/x-www-form-urlencoded") w.Header().Set("Access-Control-Allow-Origin", "*") // get all the users in the db users, err := getAllUsers() if err != nil { log.Fatalf("Unable to get all user. %v", err) } // send all the users as response json.NewEncoder(w).Encode(users)}// UpdateUser update user's detail in the postgres dbfunc UpdateUser(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/x-www-form-urlencoded") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "PUT") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") // get the userid from the request params, key is "id" params := mux.Vars(r) // convert the id type from string to int id, err := strconv.Atoi(params["id"]) if err != nil { log.Fatalf("Unable to convert the string into int. %v", err) } // create an empty user of type models.User var user models.User // decode the json request to user err = json.NewDecoder(r.Body).Decode(&user) if err != nil { log.Fatalf("Unable to decode the request body. %v", err) } // call update user to update the user updatedRows := updateUser(int64(id), user) // format the message string msg := fmt.Sprintf("User updated successfully. Total rows/record affected %v", updatedRows) // format the response message res := response{ ID: int64(id), Message: msg, } // send the response json.NewEncoder(w).Encode(res)}// DeleteUser delete user's detail in the postgres dbfunc DeleteUser(w http.ResponseWriter, r *http.Request) { w.Header().Set("Context-Type", "application/x-www-form-urlencoded") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "DELETE") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") // get the userid from the request params, key is "id" params := mux.Vars(r) // convert the id in string to int id, err := strconv.Atoi(params["id"]) if err != nil { log.Fatalf("Unable to convert the string into int. %v", err) } // call the deleteUser, convert the int to int64 deletedRows := deleteUser(int64(id)) // format the message string msg := fmt.Sprintf("User updated successfully. Total rows/record affected %v", deletedRows) // format the reponse message res := response{ ID: int64(id), Message: msg, } // send the response json.NewEncoder(w).Encode(res)}//------------------------- handler functions ----------------// insert one user in the DBfunc insertUser(user models.User) int64 { // create the postgres db connection db := createConnection() // close the db connection defer db.Close() // create the insert sql query // returning userid will return the id of the inserted user sqlStatement := `INSERT INTO users (name, location, age) VALUES ($1, $2, $3) RETURNING userid` // the inserted id will store in this id var id int64 // execute the sql statement // Scan function will save the insert id in the id err := db.QueryRow(sqlStatement, user.Name, user.Location, user.Age).Scan(&id) if err != nil { log.Fatalf("Unable to execute the query. %v", err) } fmt.Printf("Inserted a single record %v", id) // return the inserted id return id}// get one user from the DB by its useridfunc getUser(id int64) (models.User, error) { // create the postgres db connection db := createConnection() // close the db connection defer db.Close() // create a user of models.User type var user models.User // create the select sql query sqlStatement := `SELECT * FROM users WHERE userid=$1` // execute the sql statement row := db.QueryRow(sqlStatement, id) // unmarshal the row object to user err := row.Scan(&user.ID, &user.Name, &user.Age, &user.Location) switch err { case sql.ErrNoRows: fmt.Println("No rows were returned!") return user, nil case nil: return user, nil default: log.Fatalf("Unable to scan the row. %v", err) } // return empty user on error return user, err}// get one user from the DB by its useridfunc getAllUsers() ([]models.User, error) { // create the postgres db connection db := createConnection() // close the db connection defer db.Close() var users []models.User // create the select sql query sqlStatement := `SELECT * FROM users` // execute the sql statement rows, err := db.Query(sqlStatement) if err != nil { log.Fatalf("Unable to execute the query. %v", err) } // close the statement defer rows.Close() // iterate over the rows for rows.Next() { var user models.User // unmarshal the row object to user err = rows.Scan(&user.ID, &user.Name, &user.Age, &user.Location) if err != nil { log.Fatalf("Unable to scan the row. %v", err) } // append the user in the users slice users = append(users, user) } // return empty user on error return users, err}// update user in the DBfunc updateUser(id int64, user models.User) int64 { // create the postgres db connection db := createConnection() // close the db connection defer db.Close() // create the update sql query sqlStatement := `UPDATE users SET name=$2, location=$3, age=$4 WHERE userid=$1` // execute the sql statement res, err := db.Exec(sqlStatement, id, user.Name, user.Location, user.Age) if err != nil { log.Fatalf("Unable to execute the query. %v", err) } // check how many rows affected rowsAffected, err := res.RowsAffected() if err != nil { log.Fatalf("Error while checking the affected rows. %v", err) } fmt.Printf("Total rows/record affected %v", rowsAffected) return rowsAffected}// delete user in the DBfunc deleteUser(id int64) int64 { // create the postgres db connection db := createConnection() // close the db connection defer db.Close() // create the delete sql query sqlStatement := `DELETE FROM users WHERE userid=$1` // execute the sql statement res, err := db.Exec(sqlStatement, id) if err != nil { log.Fatalf("Unable to execute the query. %v", err) } // check how many rows affected rowsAffected, err := res.RowsAffected() if err != nil { log.Fatalf("Error while checking the affected rows. %v", err) } fmt.Printf("Total rows/record affected %v", rowsAffected) return rowsAffected}Let's break down the functions :
createConnection: This function will create a connection to postgreSQL Database connection and return the database connection .
Check the code in the function :
// use godotenv to load the .env fileerr := godotenv.Load(".env")// Read the POSTGRES_URL from the .env and connect to the db.db, err := sql.Open("postgres", os.Getenv("POSTGRES_URL")) stay go-postgres Create a new file in .env:
POSTGRES_URL="Postgres connection string"CreateUser: This is accessible api Request and response object handler for . It will extract the request body from the user . then , It will be called insertUser Pass the user as a parameter . insertUser Will return to insert idinsertUser: This function will execute an insert query in the database . First set up db Connect .
// create the postgres db connectiondb := createConnection()// close the db connectiondefer db.Close()establish SQL Inquire about :
sqlStatement := `INSERT INTO users (name, location, age) VALUES ($1, $2, $3) RETURNING userid`We didn't pass on users ID, Because the user ID yes SERIAL type . Its scope is 1 To 2,147,483,647.
Each insertion will add .
RETURNING userid This means that once the database is successfully inserted , Return to the user ID.
Execute insert query
var id int64err := db.QueryRow(sqlStatement, user.Name, user.Location, user.Age).Scan(&id)stay QueryRow Accept in sql Queries and parameters . stay sqlStatement in ,VALUES As a variable $1、$2、$3 Pass on . user.Name Is the first parameter , So it will replace $1. Again , All parameters will be replaced according to their position .
Use the scan to return to the user ID Decode as id
边栏推荐
- Time management understood after being urged to work at home
- [worthy of collection] centos7 installation MySQL complete operation command
- dried food! What problems will the intelligent management of retail industry encounter? It is enough to understand this article
- Jerry added an input capture channel [chapter]
- JSP自定义标签
- Four memory areas (stack, heap, global, code area)
- 千万不要错过,新媒体运营15个宝藏公众号分享
- 【On nacos】快速上手 Nacos
- R language dplyr package arrange function sorts dataframe data, sorts dataframe data through multiple data columns, specifies the first field to be sorted in descending order, and does not specify the
- 【面试高频题】难度 1.5/5,LCS 模板题
猜你喜欢

Challenges of machine learning system in production
![[tcapulusdb knowledge base] Introduction to tmonitor system upgrade](/img/04/b1194ca3340b23a4fb2091d1b2a44d.png)
[tcapulusdb knowledge base] Introduction to tmonitor system upgrade
![[tcapulusdb knowledge base] tcapulusdb doc acceptance - table creation approval introduction](/img/da/449a1e215885597a67344e2a6edf0f.png)
[tcapulusdb knowledge base] tcapulusdb doc acceptance - table creation approval introduction

怎么找相同台词的影视片段?这8个电影搜索神器,一句台词找到对应片段

JSP自定义标签

The wonderful use of 0 length array in C language

How to modify a node_ Files in modules

C/s architecture

$15.8 billion! 2021 the world's top15 most profitable hedge fund giant

等等, 怎么使用 SetMemoryLimit?
随机推荐
R language uses the polR function of mass package to construct the ordered multi classification logistic regression model, and uses the vglm function of VGAM package to test the parallelism hypothesis
QStyle类用法总结(二)
Unity Shader学习(一)认识unity shader基本结构
JSP custom tag
After Jerry's sleep, the regular wake-up system continues to run without resetting [chapter]
What is the TCP 3-time handshake process?
旭日3SDB,安装原版ros
Getting started with go web programming: validators
Nifi from introduction to practice (nanny level tutorial) - identity authentication
Fork/Join 框架基本使用和原理
C # WPF realizes undo redo function
面试突击60:什么情况会导致 MySQL 索引失效?
Jerry's DAC output mode setting [chapter]
In 2021, the global enhanced oil production surfactant revenue was about USD 202.3 million, and it is expected to reach USD 297.1 million in 2028
记一次 .NET 某物管后台服务 卡死分析
56. Core principle of flutter - flutter startup process and rendering pipeline
R语言使用epiDisplay包的poisgof函数对泊松回归(Poisson Regression)执行拟合优度检验、检验是否存在过度离散问题(overdispersion)
The R language uses the DOTPLOT function of epidisplay package to visualize the frequency of data points in different intervals in the form of point graph, specifies the grouping parameters with the b
L'utilisation de C language 0 length Array
R language dplyr package arrange function sorts dataframe data, sorts dataframe data through multiple data columns, specifies the first field to be sorted in descending order, and does not specify the