Home > Software design >  Get data from two different struct
Get data from two different struct

Time:11-09

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!

  •  Tags:  
  • go
  • Related