大家好,
在这篇文章中,我将向您展示如何将 PostgreSQL 与 GoLang 一起使用。简单介绍一下 GoLang 的历史。实际上,您可以找到不止一份关于 GoLang 历史的不同文档,但是我在一个解释得很好的网站上找到了它。历史
我体验过 .Net Core 堆栈,但是我已经学习 GoLang 3 个月了。我相信 GoLang 是非常强大和流畅的语言。我想我们会一步一步走。
步骤1.安装Docker
Step 2. 运行 PostgreSQL 容器
docker run --name postgresql-container -p 5432:5432 -e POSTGRES_PASSWORD=Password! -d postgres;
[](https://res.cloudinary.com/practicaldev/image/fetch/s--9gJMxCKe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads .s3.amazonaws.com/uploads/articles/we53z45iy3xpd2mm7h9y.png)
步骤 3. 运行数据库脚本
-- Drop table
-- DROP TABLE public.users;
CREATE TABLE public.users (
firstname varchar NULL,
lastname varchar NULL,
id serial NOT NULL
);
Insert Into public.Users(firstname,lastname) values("FirstName-1","LastName-1")
Insert Into public.Users(firstname,lastname) values("FirstName-2","LastName-2")
Insert Into public.Users(firstname,lastname) values("FirstName-3","LastName-3")
进入全屏模式 退出全屏模式
步骤 4. 创建新的 GoLang 解决方案
有不同的IDE 的开发代码。
-
VS代码
-
Vim-go
-
原子
-
崇高
-
LiteIDE 更多信息GoLang 官方
根据我的习惯,Visual Studio Code 非常适合我。现在安装 GoLang 的扩展。转分机
包装:
-
Web 框架:go get -u github.com/labstack/echo/v4
-
读取配置文件:go get -u github.com/spf13/viper
-
日志记录:去获取-u github.com/sirupsen/logrus
-
PostgreSQL:去获取-u github.com/lib/pq
看看项目结构
[](https://res.cloudinary.com/practicaldev/image/fetch/s--aXszQRQ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads .s3.amazonaws.com/uploads/articles/umgsek4q2fydgw8acumx.png)
-
cmd>api:包括配置文件和初始化,如 Startup.cs
-
cmd>utils:配置结构
-
pkg>api : 包括中间件和路由也向处理程序注册
-
pkg>entities:数据库实体
-
pkg>handlers:与请求和响应类型相关,也与存储库层交互
-
pkg>models : api 响应数据
-
pkg>repository:与数据库操作相关
go run main.go
让我们连接到数据库。此函数采用 postgresCustomerRepository 参数并返回 *sql.DB 指针。此方法与打开连接有关,使用 Ping 命令检查连接状态。
func openDatabaseConn(r *postgresCustomerRepository) *sql.DB {
db, err := sql.Open("postgres", r.conn)
if err != nil {
log.Error("Connection failed")
}
pingError := db.Ping()
if pingError != nil {
log.Error("Ping != pong")
}
log.Info("Postgres connection success!!!")
return db
}
进入全屏模式 退出全屏模式
添加方法
$1 和 $2 持有 struct 的参数。在旧的数值方法中,使用语法 $n 引用参数:$1 引用第一个输入参数,$2 引用第二个输入参数,依此类推。无论是否使用名称声明了特定参数,这都将起作用。 [PostgreSQL][https://www.postgresql.org/docs/9.5/xfunc-sql.html]
db := openDatabaseConn(r)
defer db.Close()
//add data
query := "Insert into Users(FirstName, LastName) values($1,$2)"
if _, err := db.ExecContext(ctx, query, customer.FirstName, customer.LastName); err != nil {
return customer, err
}
进入全屏模式 退出全屏模式
列表法
//connect database
db := openDatabaseConn(r)
defer db.Close()
//read data from server
rows, _ := db.QueryContext(ctx, "Select id,firstname,lastname from Users")
defer rows.Close()
进入全屏模式 退出全屏模式
删除方法
db := openDatabaseConn(r)
defer db.Close()
query := "Delete From Users Where Id=$1"
affectedRow, err := db.ExecContext(ctx, query, id)
if err != nil {
return false, nil
}
进入全屏模式 退出全屏模式
得到一个
db := openDatabaseConn(r)
defer db.Close()
data := db.QueryRowContext(ctx, "Select id,firstname,lastname from Users Where Id=$1", id)
进入全屏模式 退出全屏模式
customerRepository.go 文件
package repository
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/bburaksseyhan/ctmapp/src/cmd/utils"
"github.com/bburaksseyhan/ctmapp/src/pkg/entities"
_ "github.com/lib/pq"
log "github.com/sirupsen/logrus"
)
type CustomerRepository interface {
List(cntxt context.Context, timeout int) ([]entities.CustomerEntity, error)
Add(customer entities.CustomerEntity, cntxt context.Context, timeout int) (entities.CustomerEntity, error)
Delete(id int, cntxt context.Context, timeout int) (bool, error)
Get(id int, cntxt context.Context, timeout int) (entities.CustomerEntity, error)
}
type postgresCustomerRepository struct {
dbSetting *utils.DbSettings
conn string
}
func NewPostgresCustomerRepository(dbSettings *utils.DbSettings) CustomerRepository {
//initial log formatter
log.SetFormatter(&log.JSONFormatter{})
repo := &postgresCustomerRepository{
dbSetting: dbSettings,
conn: fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
dbSettings.Host, dbSettings.Port, dbSettings.User, dbSettings.Password, dbSettings.DbName),
}
return repo
}
func (r *postgresCustomerRepository) List(cntxt context.Context, timeout int) ([]entities.CustomerEntity, error) {
//context
ctx, cancel := context.WithTimeout(cntxt, time.Duration(timeout)*time.Second)
defer cancel()
//connect database
db := openDatabaseConn(r)
defer db.Close()
//read data from server
rows, _ := db.QueryContext(ctx, "Select id,firstname,lastname from Users")
defer rows.Close()
//define slice for store customer information
var customerEntity []entities.CustomerEntity
//read data row by row
for rows.Next() {
var userId int
var firstName string
var lastName string
_ = rows.Scan(&userId, &firstName, &lastName)
customerEntity = append(customerEntity, entities.CustomerEntity{Id: userId, FirstName: firstName, LastName: lastName})
}
return customerEntity, nil
}
func (r *postgresCustomerRepository) Add(customer entities.CustomerEntity, cntxt context.Context, timeout int) (entities.CustomerEntity, error) {
ctx, cancel := context.WithTimeout(cntxt, time.Duration(timeout)*time.Second)
defer cancel()
db := openDatabaseConn(r)
defer db.Close()
//add data
query := "Insert into Users(FirstName, LastName) values($1,$2)"
if _, err := db.ExecContext(ctx, query, customer.FirstName, customer.LastName); err != nil {
return customer, err
}
return customer, nil
}
func (r *postgresCustomerRepository) Delete(id int, cntxt context.Context, timeout int) (bool, error) {
ctx, cancel := context.WithTimeout(cntxt, time.Duration(timeout)*time.Second)
defer cancel()
db := openDatabaseConn(r)
defer db.Close()
query := "Delete From Users Where Id=$1"
affectedRow, err := db.ExecContext(ctx, query, id)
if err != nil {
return false, nil
}
fmt.Println(affectedRow.LastInsertId())
fmt.Println(affectedRow.RowsAffected())
return true, nil
}
func (r *postgresCustomerRepository) Get(id int, cntxt context.Context, timeout int) (entities.CustomerEntity, error) {
ctx, cancel := context.WithTimeout(cntxt, time.Duration(timeout)*time.Second)
defer cancel()
db := openDatabaseConn(r)
defer db.Close()
data := db.QueryRowContext(ctx, "Select id,firstname,lastname from Users Where Id=$1", id)
var userId int
var firstName string
var lastName string
_ = data.Scan(&userId, &firstName, &lastName)
return entities.CustomerEntity{Id: userId, FirstName: firstName, LastName: lastName}, nil
}
func openDatabaseConn(r *postgresCustomerRepository) *sql.DB {
db, err := sql.Open("postgres", r.conn)
if err != nil {
log.Error("Connection failed")
}
pingError := db.Ping()
if pingError != nil {
log.Error("Ping != pong")
}
log.Info("Postgres connection success!!!")
return db
}
进入全屏模式 退出全屏模式
测试
go run main.go
[图像描述">](https://res.cloudinary.com/practicaldev/image/fetch/s--84RWI4TI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/d85laoxngumuodvzn9yy.png)
路由
e.GET("/health", customerHandler.Health)
e.GET("/api/v1/customer", customerHandler.List)
e.POST("/api/v1/customer", customerHandler.Add)
e.DELETE("/api/v1/customer/:id", customerHandler.Delete)
e.GET("api/v1/customer/:id", customerHandler.Get)
进入全屏模式 退出全屏模式
创建用户
[图像描述">](https://res.cloudinary.com/practicaldev/image/fetch/s--GKCbWkUM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/sf7jf5zmdthfcq794sc6.png)
列出用户
[图像描述">](https://res.cloudinary.com/practicaldev/image/fetch/s--IofRxE3P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/9jaiyu9mnyxnxsshjy0k.png)
通过id获取
[图像描述">](https://res.cloudinary.com/practicaldev/image/fetch/s--tQXYXTPm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/yxp7bg9t7o6l8vj0qmmi.png)
删除
[图像描述">](https://res.cloudinary.com/practicaldev/image/fetch/s--zKYRCkiv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/59faez5xkidg14o1v979.png)
[图像描述">](https://res.cloudinary.com/practicaldev/image/fetch/s--R7mVHn7e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/2bspub9m8kaaxb9nfq47.png)
存储库
谢谢你。