Have this struct of User and Post and I try to make Name from User to be included within Post Struct when a user create a new post.
type User struct {
ID int
Name string
Created time.Time
}
type Post struct {
ID int
PostTitle string
PostDesc string
Created time.Time
}
How can I create something connected between this two struct such as Author of the Post ?
The goal is try to get the name of the post author which from User struct with the code below:
post, err := app.Models.Posts.GetPost(id)
GetPost() just run SELECT query and scan row
CodePudding user response:
This approach is without any ORM.
It's a simple query that can return multiple rows. You've to scan the whole resultset and map each column on the struct's fields.
Keep in mind to always check for errors.
Below you can find the solution:
package main
import (
"database/sql"
"fmt"
"time"
_ "github.com/lib/pq"
)
type Post struct {
ID int
PostTitle string
PostDesc string
Created time.Time
UserID int
User User
}
type User struct {
ID int
Name string
Created time.Time
}
func main() {
conn, err := sql.Open("postgres", "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable")
if err != nil {
panic(err)
}
defer conn.Close()
rows, err := conn.Query(`SELECT posts.id, post_title, post_desc, posts.created, users.id, users.name, users.created FROM posts INNER JOIN users ON posts.user_id=users.id`)
if err != nil {
panic(err)
}
var posts []Post
for rows.Next() {
var post Post
if err = rows.Scan(&post.ID, &post.PostTitle, &post.PostDesc, &post.Created, &post.User.ID, &post.User.Name, &post.User.Created); err != nil {
panic(err)
}
posts = append(posts, post)
}
if err = rows.Err(); err != nil {
panic(err)
}
for _, v := range posts {
fmt.Printf("author name: %q\n", v.User.Name)
}
}
Let me know if this helps.
CodePudding user response:
Give it a try to this solution, maybe it resolves your issue.
First, I defined the structs in this way:
// "Post" belongs to "User", "UserID" is the foreign key
type Post struct {
gorm.Model
ID int
PostTitle string
PostDesc string
Created time.Time
UserID int
User User
}
type User struct {
ID int
Name string
Created time.Time
}
In this way, you can say that Post
belongs to User
and access the User's information within the Post
struct.
To query the records, you've to use Preload("User")
to be sure to eager load the User records from the separate table.
Keep attention to the name you pass in as the argument in
Preload
, as it can be tricky.
Lastly, you'll be able to access data in the embedded struct (with the dot
notation).
Below, you can find a complete working example (implemented with the use of Docker):
package main
import (
"fmt"
"time"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
// "Post" belongs to "User", "UserID" is the foreign key
type Post struct {
gorm.Model
ID int
PostTitle string
PostDesc string
Created time.Time
UserID int
User User
}
type User struct {
ID int
Name string
Created time.Time
}
func main() {
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
db.AutoMigrate(&Post{})
newPost := &Post{ID: 1, PostTitle: "Golang", PostDesc: "Introduction to Golang", Created: time.Now(), UserID: 1, User: User{ID: 1, Name: "John Doe", Created: time.Now()}}
db.Create(newPost)
var post Post
db.Preload("User").Find(&post, 1)
fmt.Printf("author name: %q\n", post.User.Name)
}
Let me know if I answered your question!