英文:
Go structs that represent SQL tables
问题
我对Go语言还不太熟悉,但我可以尝试为你提供一些帮助。在Go中,你可以使用数据库/ORM库来简化与数据库的通信。ORM(对象关系映射)库可以帮助你将对象映射到数据库表,并提供方便的方法来执行插入和更新操作,而无需编写原始的SQL语句。
在Go中,一些常用的ORM库包括GORM、XORM和SQLBoiler等。你可以选择其中一个库来帮助你简化数据库通信的过程。
以下是使用GORM库的示例代码,展示了如何定义模型、插入数据和更新数据:
import (
"gorm.io/gorm"
"gorm.io/driver/postgres"
)
type Patients struct {
gorm.Model
Name string
Image string
}
func InsertPatient(patient Patients) error {
db, err := gorm.Open(postgres.Open("your-database-connection-string"), &gorm.Config{})
if err != nil {
return err
}
err = db.Create(&patient).Error
if err != nil {
return err
}
return nil
}
func UpdatePatient(patient Patients) error {
db, err := gorm.Open(postgres.Open("your-database-connection-string"), &gorm.Config{})
if err != nil {
return err
}
err = db.Save(&patient).Error
if err != nil {
return err
}
return nil
}
在上面的代码中,我们使用GORM库定义了一个Patients
结构体,并使用gorm.Model
嵌入了一些常用的字段(如ID、CreatedAt、UpdatedAt等)。然后,我们定义了InsertPatient
和UpdatePatient
函数来执行插入和更新操作。
你需要将your-database-connection-string
替换为你的实际数据库连接字符串。然后,你可以在其他地方调用这些函数来插入和更新数据,而无需编写原始的SQL语句。
请注意,这只是一个示例,你可以根据自己的需求进行修改和扩展。希望对你有所帮助!
英文:
I am pretty new to Go and I am trying to find the best way to set up my db communication. Essentially I remember from my previous workplaces that in PHP you can create a class that represents a SQL table and when you need to insert data into your db you would create an object of that class with all the necessary data, call insert(), pass your object and it would insert that data into a corresponding table without you writing any SQL code, update() works in a very similar way except it would update instead of inserting. Unfortunately, I don't remember the name of that PHP framework but maybe someone knows a way to achieve something like that in Go or is it not a thing?
Lets say I have a struct:
type Patients struct {
ID int
Name string
Image string
}
Now I want to have a function that takes Patients objet as a parameter and inserts it into a patients postgres table automatically converting patient into what postgres expects:
func (patients *Patients) insert(patient Patients) {
}
And then update()
would take a Patients object and basically perform this chunk of code without me writing it:
stmt := `update patients set
name = $1,
image = $2,
where id = $3
`
_, err := db.ExecContext(ctx, stmt,
patient.Name,
patient.Image,
patient.ID
)
答案1
得分: 3
你正在寻找一种称为ORM(对象关系映射器)的东西。在Go语言中有几种选择,但最流行的是GORM。这是一个有争议的话题,但我认为如果你是Go语言和/或数据库的新手,使用ORM是一个不错的选择。它可以节省你很多时间和精力。
另一种选择是使用database/sql包并编写自己的SQL查询语句。如果你是经验丰富的Go开发人员和/或数据库管理员,这是一个不错的选择。它可以让你更好地控制查询,并且更高效。推荐阅读:https://www.alexedwards.net/blog/organising-database-access。这种方法推荐使用的库包括sqlx和pgx。
以下是将你的结构体作为GORM模型的示例:
type Patient struct {
ID int `gorm:"primaryKey"`
Name string
Image string
}
以下是将患者插入数据库的示例程序:
package main
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Patient struct {
ID int `gorm:"primaryKey"`
Name string
Image string
}
func main() {
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable TimeZone=UTC"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&Patient{})
patient := Patient{
Name: "John Smith",
Image: "https://example.com/image.png",
}
result := db.Create(&patient)
if result.Error != nil {
panic(result.Error)
}
fmt.Println(patient)
}
如果你想使用sqlx,可以编写类似以下的代码:
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
type Patient struct {
ID int
Name string
Image string
}
func main() {
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable TimeZone=UTC"
db, err := sql.Open("postgres", dsn)
if err != nil {
log.Fatal(err)
}
defer db.Close()
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS patients (
id SERIAL PRIMARY KEY,
name TEXT,
image TEXT
)
`)
if err != nil {
log.Fatal(err)
}
patient := Patient{
Name: "John Smith",
Image: "https://example.com/image.png",
}
_, err = db.Exec(`
INSERT INTO patients (name, image) VALUES ($1, $2)
`, patient.Name, patient.Image)
if err != nil {
log.Fatal(err)
}
fmt.Println(patient)
}
当然,使用ORM来管理数据库模式会更加复杂。你可以使用迁移工具,但我更喜欢使用一个叫做goose的工具。它的设置可能有点麻烦,但非常强大和灵活。以下是如何使用它的示例:
package main
import (
"fmt"
"log"
"github.com/pressly/goose"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Patient struct {
ID int `gorm:"primaryKey"`
Name string
Image string
}
func main() {
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable TimeZone=UTC"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
goose.SetDialect("postgres")
goose.SetTableName("schema_migrations")
err = goose.Run("up", db.DB(), "migrations")
if err != nil {
log.Fatal(err)
}
patient := Patient{
Name: "John Smith",
Image: "https://example.com/image.png",
}
result := db.Create(&patient)
if result.Error != nil {
panic(result.Error)
}
fmt.Println(patient)
}
其中,你的迁移目录结构如下:
migrations/
00001_create_patients.up.sql
00001_create_patients.down.sql
你的迁移文件内容如下:
-- 00001_create_patients.up.sql
CREATE TABLE patients (
id SERIAL PRIMARY KEY,
name TEXT,
image TEXT
);
-- 00001_create_patients.down.sql
DROP TABLE patients;
希望对你有所帮助!如果有任何问题,请随时告诉我。
英文:
You are looking for something called an ORM (Object Relational Mapper). There are a few in Go, but the most popular is GORM. It's a bit of a controversial topic, but I think it's a good idea to use an ORM if you're new to Go and/or databases. It will save you a lot of time and effort.
The alternative is to use the database/sql package and write your own SQL queries. This is a good idea if you're an experienced Go developer and/or database administrator. It will give you more control over your queries and will be more efficient. Recommended reading: https://www.alexedwards.net/blog/organising-database-access. Recommended libraries for this approach include sqlx and pgx.
Here is what your struct would look like as a GORM model:
type Patient struct {
ID int `gorm:"primaryKey"`
Name string
Image string
}
And here is an example program for how to insert a patient into the database:
package main
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Patient struct {
ID int `gorm:"primaryKey"`
Name string
Image string
}
func main() {
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable TimeZone=UTC"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&Patient{})
patient := Patient{
Name: "John Smith",
Image: "https://example.com/image.png",
}
result := db.Create(&patient)
if result.Error != nil {
panic(result.Error)
}
fmt.Println(patient)
}
If instead you wanted to use sqlx, you would write something like this:
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
type Patient struct {
ID int
Name string
Image string
}
func main() {
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable TimeZone=UTC"
db, err := sql.Open("postgres", dsn)
if err != nil {
log.Fatal(err)
}
defer db.Close()
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS patients (
id SERIAL PRIMARY KEY,
name TEXT,
image TEXT
)
`)
if err != nil {
log.Fatal(err)
}
patient := Patient{
Name: "John Smith",
Image: "https://example.com/image.png",
}
_, err = db.Exec(`
INSERT INTO patients (name, image) VALUES ($1, $2)
`, patient.Name, patient.Image)
if err != nil {
log.Fatal(err)
}
fmt.Println(patient)
}
Of course, managing your database schema is a bit more complicated with an ORM. You can use migrations, but I prefer to use a tool called goose. It's a bit of a pain to set up, but it's very powerful and flexible. Here is an example of how to use it:
package main
import (
"fmt"
"log"
"github.com/pressly/goose"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Patient struct {
ID int `gorm:"primaryKey"`
Name string
Image string
}
func main() {
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable TimeZone=UTC"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
goose.SetDialect("postgres")
goose.SetTableName("schema_migrations")
err = goose.Run("up", db.DB(), "migrations")
if err != nil {
log.Fatal(err)
}
patient := Patient{
Name: "John Smith",
Image: "https://example.com/image.png",
}
result := db.Create(&patient)
if result.Error != nil {
panic(result.Error)
}
fmt.Println(patient)
}
where your migrations directory looks like this:
migrations/
00001_create_patients.up.sql
00001_create_patients.down.sql
and your migrations look like this:
-- 00001_create_patients.up.sql
CREATE TABLE patients (
id SERIAL PRIMARY KEY,
name TEXT,
image TEXT
);
-- 00001_create_patients.down.sql
DROP TABLE patients;
I hope this helps! Let me know if you have any questions.
答案2
得分: 0
我认为你正在寻找的是一个ORM(对象关系映射)。ORM是一个库,它可以接收语言结构并自动处理SQL逻辑。
在Go语言中,最流行的ORM库是GORM。这是他们的主页链接:https://gorm.io/。我在生产环境中广泛使用过它,使用体验很好!
文档中有一个很好的示例,你可以看一下:https://gorm.io/docs/。
希望对你有帮助。
英文:
I think what you're looking for is an ORM. An ORM is a library that essentially does this, taking language structures and automatically handling the SQL logic for you.
The most popular library for this in Go is GORM. Here's a link to their home page: https://gorm.io/. I've used it heavily in production and it's been a good experience!
The docs have a good example of what it'll look like.
Hope this helps.
答案3
得分: 0
其他答案提到了GORM以及一些更底层的工具,如database/sql
、sqlx
和pgx
,它们都很好。
但是我确实发现了GORM和这些更底层工具存在一些问题,我在这篇文章中对我发现的这些问题进行了一些解释:
https://medium.com/better-programming/golang-sql-problems-with-existing-libraries-145a037261b8
在同一篇文章中,我还推广了我编写的一个解决方案,叫做KSQL(不是Kafka的那个),它比GORM简单得多,比database/sql
、sqlx
和pgx
强大得多,你可能会喜欢。
这个想法是为常见操作(如Insert()
、Update()
和Delete()
)提供一些辅助函数,但是对于其他所有操作,KSQL只需让你自己编写查询语句,因此只要了解SQL就足以使用这个库,而使用GORM之前需要学习很多关于GORM库本身的知识。
你可以在这里找到它:
https://github.com/vingarcia/ksql
这里有一个简短的示例,演示如何使用KSQL将患者插入数据库:
package main
import (
"context"
"fmt"
"github.com/vingarcia/ksql"
"github.com/vingarcia/ksql/adapters/kpgx"
)
type Patient struct {
ID int `ksql:"id"`
Name string `ksql:"name"`
Image string `ksql:"image"`
}
// Just a simple struct containing the table name and
// the name of the ID column or columns:
var PatientsTable = ksql.NewTable("patients", "id")
func main() {
ctx := context.Background()
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable TimeZone=UTC"
db, err := kpgx.New(ctx, dsn, ksql.Config{})
if err != nil {
panic("failed to connect database")
}
patient := Patient{
Name: "John Smith",
Image: "https://example.com/image.png",
}
err = db.Insert(ctx, PatientsTable, &patient) // (this call will retrieve the inserted ID automatically)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", patient) // {ID:1 Name:John Smith Image:https://example.com/image.png}
}
英文:
Other answers mention both GORM and a few lower level tools like database/sql
, sqlx
and pgx
, which are great.
But I do see some issues with both GORM and the lower level tools, I do explain a little about these issues I see in this article:
https://medium.com/better-programming/golang-sql-problems-with-existing-libraries-145a037261b8
In this same article I am also promoting a solution I wrote called KSQL (not the Kafka one), that is a lot simpler than GORM and a lot more powerful than database/sql
, sqlx
and pgx
, you might like it.
The idea is to offer a few helper functions for common operations like Insert()
, Update()
and Delete()
but for everything else KSQL just let's you write the query yourself, so knowing SQL is enough to use this library, while with GORM you need to learn a lot about the GORM library itself before using it well.
You can find it here:
https://github.com/vingarcia/ksql
And here is a short example of how one would go about inserting a patient into the database using KSQL:
package main
import (
"context"
"fmt"
"github.com/vingarcia/ksql"
"github.com/vingarcia/ksql/adapters/kpgx"
)
type Patient struct {
ID int `ksql:"id"`
Name string `ksql:"name"`
Image string `ksql:"image"`
}
// Just a simple struct containing the table name and
// the name of the ID column or columns:
var PatientsTable = ksql.NewTable("patients", "id")
func main() {
ctx := context.Background()
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable TimeZone=UTC"
db, err := kpgx.New(ctx, dsn, ksql.Config{})
if err != nil {
panic("failed to connect database")
}
patient := Patient{
Name: "John Smith",
Image: "https://example.com/image.png",
}
err = db.Insert(ctx, PatientsTable, &patient) // (this call will retrieve the inserted ID automatically)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", patient) // {ID:1 Name:John Smith Image:https://example.com/image.png}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论