Golang import package remove by vscode - go

I start to work with go and i am happy :)
But i got a strange problem with package import.
I got a file dto.go :
package dto
import (
"time"
)
type TaskResponse struct {
ID uint `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
A simple response object, but a task have a Status param.
I got a file model.go :
package model
// Status struct
type Status struct {
ID uint
Name string
}
The problem is that i would like to add in TaskResponse the Status object, but when i add this, i got a "undefined Status" and when i force the import of the package vscode remove it automaticly...
Someone know what is my problem ?
Thanks in advance

I found the problem, just need to use model.Status in the object TaskResponse

The reason why this happening is because of what you imported, you didn't use it in the program, so Golang deletes unnecessary dependencies.

Related

GO: import a struct and rename it in json

I have built a database in go with gorm. For this I created a struct and with this struct I created a table. So far so good. In the backend everything works, but in the frontend the problem is that the JSON which is called always returns the ID in upper case and swagger generates me an ID which is lower case. Is there a way in Go that I can overwrite the imported struct from gorm with a JSON identifier?
import "gorm.io/gorm"
type Report struct {
gorm.Model
CreatedBy User `gorm:"foreignKey:CreatedByUserID" json:"createdBy"`
Archived bool `json:"archived"`
}
This Struct gives me the following response
{
"ID": 8,
"CreatedAt": "2022-11-15T20:45:16.83+01:00",
"UpdatedAt": "2022-12-27T21:34:17.871+01:00",
"DeletedAt": null
"createdBy": {
"ID": 1,
"CreatedAt": "2022-11-15T20:02:17.497+01:00",
"UpdatedAt": "2022-11-15T20:02:17.497+01:00",
...
},
"archived": true,
}
Is there a way to make the ID lowercase (like Archived)? Or can I adjust it at swaggo so that it is generated in upper case.
What I have seen is that you can make the table without this gorm.Model and define all the attributes yourself. The problem is that I then have to create all the functionalities (delete, update, index, primary key, ...) of these columns myself.
You can use the mapstructure package.
mapstructure is a Go library for decoding generic map values to structures and vice versa
If you want to embed ID field from gorm.Model with custom json tag, and you want it to be on the same struct and not in a "substruct", you can use mapstructure:",squash" tag on the embedded model.
type Model struct {
ID uint `json:"id"`
}
type Report struct {
Model `mapstructure:",squash"`
Archived bool `json:"archived"`
}
func main() {
input := map[string]interface{}{
"id": 1,
"archived": false,
}
var report Report
if err := mapstructure.Decode(input, &report); err != nil {
panic(err)
}
fmt.Println("Report ID:", report.ID)
fmt.Println("Report ID via Model:", report.Model.ID)
}
As you can observe, with mapstructure.Decode method you can convert map to struct with the squash option, and you can then access ID of report directly. Note that you can still access report.Model and all its fields.
With mapstructure, you can make the ID lowercase as you wanted, and also accessable from the report struct directly, not only from a Model substruct.
I create my own gorm-model-struct:
type GormModel struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deletedAt"`
} //#name models.gormModel
I import this struct into the other structs:
type Report struct {
GormModel
CreatedBy User `gorm:"foreignKey:CreatedByUserID" json:"createdBy"`
Archived bool `json:"archived"`
}
Important is, that you add the json-key and set the attribute name.

Golang GORM Delete with Select

I'm trying to cascade delete the below structure:
type Action struct {
gorm.Model
Name string
Email string
Halls []Hall `gorm:"foreignKey:ActionID"`
}
type Hall struct {
gorm.Model
Name string
ActionID uint
Stream Stream `gorm:"foreignKey:HallID"`
}
type Stream struct {
ID uint `gorm:"primaryKey"`
HallID uint
Name string
}
db.Select("Halls").Delete(&action) - works fine for selected action and with all related halls.
How can I delete this one and related streams?
Something like:
db.Select("Halls", "Streams").Delete(&action)
db.Select("Streams").Select("Halls").Delete(action)
doesn't work.
Thanks
you can not use delete and select at same time in same query means it not feasible solution to do that
but yeah you can use this reference link
Try Deleting action with where condition and specify HallID
db.Where("hall_id IN ?",HallID).Delete(&action)
and SET HallID to constraint:OnDelete:CASCADE in Stream so when you delete Halls then automatically Streams will be deleted whichever associated with that Halls
I cannot comment on M_x so I'll put this as an answer.
You are allowed to 'Delete' with 'Select' with associations. See https://gorm.io/docs/associations.html#Delete-with-Select
However, I'm also looking for a solution for nested associations where the nested is a slice of a struct.

Error when using preload gorm golang, it's not running the preload table i need

I tried to learn and define a model in gorm golang
But i got this problem... dont know how to find the issue.
Firstly I have created 2 table name User and Schedule in database
this is the model
type User struct {
UserId int `json:",omitempty" gorm:"primaryKey"`
UserName string `json:",omitempty"`
UserPassword string `json:"-"`
UserEmail string `json:",omitempty"`
UserFullName string `json:",omitempty"`
Schedule []*Schedule `gorm:"foreignKey:UserId" json:"working_schedule"`
}
type Schedule struct {
ScheduleId int `gorm:"primaryKey"`
ScheduleDate int
ScheduleStart int
ScheduleEnd int
ScheduleType int
ScheduleCreated int
UserId int
}
And i also do this code in golang for making an query to get all the schedule of specific user by the id i get.
Preload("Schedule").Table("user").Find(&user, "user_id=?", id)
But when showing the result at all the working_schedule is null. And I tried to debug the code above but only found that it just run a select from user... not in schedule
SELECT * FROM `user` WHERE user_id=1
Idk what I was wrong. Please help me. Ty
Since you named your struct Schedule, go-gorm will try to find a table named schedules, because it uses the pluralized snake-case convention. If it doesn't succeed, it will not create a query for it when doing preload.
If your database table is named schedule, you will have to implement the Tabler interface (maybe below the definition of your Schedule struct).
func (Schedule) TableName() string {
return "schedule"
}
You can find more info on this here.

GORM updating null field when calling Updates()?

According to GORM's docs:
Updates supports update with struct or map[string]interface{}, when
updating with struct it will only update non-zero fields by default
I have an entry in my database already for the Service with ID, abc123. I am attempting to take an object that looks like the one below:
Service{
ID: "abc123",
Name: "new service name",
CreatedAt: nil,
}
And use it to update the my existing record. But when I call:
tx.Model(&service).Updates(service)
the CreatedAt value in the database is overwritten with nil. How can I update my database record without overwritting the CreatedAt value?
Update: Below is my Service struct
type Service struct {
ID string `gorm:"not null;type:char(32);primary_key;column:id"`
Name string `json:"name" gorm:"size:50;not null;"`
CreatedAt *time.Time
UpdatedAt time.Time
DeletedAt *time.Time `gorm:"index"`
}
I've tried two different variations for my Service struct. the other is with CreatedAt being of type time.Time instead of *time.Time. With *time.Time it will overwrite the value in my DB with a null value. With time.Time it attempts to overwrite the value in the DB with an uninitialized time value and throws the error: Error 1292: Incorrect datetime value: '0000-00-00' for column 'created_at' at row 1
By default, gorm will not update default(zero) or nil values.
If you want to have control over it use something as I described below.
You can use nullable types provided by sql package or create your own.
type Model struct {
Amount *sql.NullFloat64
}
// amount will not be updated
gorm.Updates(Model{Amount: nil})
// amount will be updated as a null
gorm.Updates(Model{Amount: &sql.NullFloat64{}})
// amount will be updated as a 10.50
gorm.Updates(Model{Amount: &sql.NullFloat64{Float64: 10.50, Valid: true}})
A zero value, or a default value, for a time.Time field type inside a struct is time.Time{}. When using Updates, either don't populate the CreatedAt field, or assign time.Time{} value to it.
In the example below, the default or zero value is printed out for CreatedAt field in both cases.
package main
import (
"fmt"
"time"
)
type T struct {
CreatedAt time.Time
C int
S string
}
func main() {
fmt.Println(T{C: 1, S: "one"})
fmt.Println(T{C: 2, S: "two", CreatedAt: time.Time{}})
}
// {0001-01-01 00:00:00 +0000 UTC 1 one}
// {0001-01-01 00:00:00 +0000 UTC 2 two}
EDIT:
Also, I'm not sure how even CreatedAt: nil, compiles if the CreatedAt field is of time.Time type, and not *time.Time.
Since you've updated the Service struct and CreatedAt field type to *time.Time, following should work:
tx.Model(&service).Updates(Service{Name: service.Name}) // add all fields that you want to be updated.
// resulting query
// UPDATE services SET name = 'new service name' WHERE id = 'abc123';
An official GORM example is here
Additionally, you can omit the created_at field like this:
tx.Model(&service).Omit("created_at").Updates(service)
use map
https://gorm.io/docs/update.html#Updates-multiple-columns
tx.Model(&service).Updates(map[string]interface{}{"ID": "abc123", "Name": "new service name", "CreatedAt": nil})

Merging 2 structures with different types

I have two structures.
EventForm is the structure that is used to parse the POST body of a request.
EventTable is used for creating the MYSQL table structure and finding/creating rows.
I want to merge EventForm with EventTable so that fields like ID cannot be overridden via the POST body. I am not able to convert the type of EventForm to EventTable since you cannot convert a struct to a different type if the fields do not 100% match. So my question is what is the best way to merge these two structs? If it is not plausible to merge these two structs how could I best solve this problem?
package models
import "time"
// EventTable table structure of "events"
type EventTable struct {
EventForm `xorm:"extends"`
ID int `xorm:"autoincr pk 'id'" json:"id"`
Created time.Time `xorm:"not null created" json:"created"`
Updated time.Time `xorm:"not null updated" json:"updated"`
}
// TableName table name of EventTable
func (u *EventTable) TableName() string {
return "events"
}
// EventForm the structure that is received via an API call
type EventForm struct {
Title string `xorm:"not null" json:"title" required:"true"`
Description string `xorm:"not null" json:"description" required:"true"`
Owner string `xorm:"not null" json:"owner" required:"true"`
Lat string `xorm:"not null" json:"lat" required:"true"`
Lng string `xorm:"not null" json:"lng" required:"true"`
}
I am with #mkopriva and don't fully understand what the problem is. Assuming you are receiving EventForm from some API call
evtForm := GetSomeEventForm()
evtTable := &models.EventTable{ EventForm: evtForm, Created: time.Now() }
someORMProbably.Insert(evtTable)

Resources