golang read private attribute of a struct in another package - go

I understand on golang we have public and private fields
package main
type User struct {
DisplayName string
title *string
}
Displayname is public so I can read it from another package. title is private I cannot read direclty
what about I add a public method like this
package main
type User struct {
DisplayName string
title *string
}
func (user *User) PublicTitle() string {
return user.title
}
type EmployeeUser User
So I should be able to read title by localUser.PublicTitle() in another package?
package utility
var localUser *main.EmployeeUser
localUser.PublicTitle()
I have tried it seems not working. I am a bit confused.
Thanks for help

The type EmployeeUser is a new type. When you define a new type based on an existing one, the methods of base type are not promoted to the new type.
To do that, you have to embed:
type EmployeeUser struct {
User
}

Related

How do I store the data from DTO Gorm

I am using golang fiber and GORM. I am trying to store the data from DTO. For example, I have created a post entity and post dto like below.
type User struct {
gorm.Model
Name string
Address string
Phone string
}
This is my DTO
type PostDto struct {
Name string `json:"name"`
Address string `json:"address"`
Phone string `json:"phone"`
}
I am trying to store the data like below
var postDto models.PostDto
c.BodyParser(&postDto)
err := database.DB.Model(models.User{}).Create(&postDto).Error
fmt.Println(err.Error())
But I am getting the below error
panic: reflect: call of reflect.Value.Field on string Value
Could anyone help to resolve this issue?
Thanks in advance
I don't know what you are doing? this is go language, not java, why do you define two structs?
You can use tag to complete that you want.
type User struct {
gorm.Model `json:"-" gorm:"-"`
Name string `json:"name" gorm:"column:name"`
Address string `json:"address" gorm:"column:address"`
Phone string `json:"phone" gorm:"column:phone"`
}
var user User
err := database.DB.Model(User{}).Create(&user).Error
fmt.Println(err.Error())
User and PostDto structures are not same, using one model to get and save data from another is wrong.
Either create a function to convert from PostDto to User, adn use its output in Create
func (postDTo PostDTo) ToUser() *User {
return &User{Name: postDTo.Name, Address: postDTo.Address, Phone: postDTo.Phone}
}
OR, as User and PostDto structs are so similar, add json ignore to gorm.Model in User and use it instead of PostDto
type User struct {
gorm.Model `json:"-"`
Name string `json:"name"`
Address string `json:"address"`
Phone string `json:"phone"`
}
var postData models.User
c.BodyParser(&postData)

GORM embedded struct not working correctly

I receive this error
controllers/users.go:61:36: user.ID undefined (type models.User has no field or method ID)
when using
var user models.User
...
jwtToken, err := generateJWT(user.ID, user.Username)
The definition of User model:
package models
import "time"
type BaseModel struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
}
type User struct {
BaseModel BaseModel `gorm:"embedded"`
Username string `json:"username"`
Password string `json:"password"`
}
Actually I put BaseModel in different file but in the same package with User. Migration works fine as table users have all columns in BaseModel. What is the problem? I use golang 1.18 and latest version of GORM
You have used BaseModel as attribute in your model so even though gorm can very well map it to the table column to access it, you have to use the attribute name
To access you would do
jwtToken, err := generateJWT(user.BaseModel.ID, user.Username)
you could also try this next code to see if it works otherwise the above will work for sure
type BaseModel struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
}
type User struct {
BaseModel `gorm:"embedded"`
Username string `json:"username"`
Password string `json:"password"`
}
now you might be able to access it like your original pattern
jwtToken, err := generateJWT(user.ID, user.Username)

How add new fields to the existing type in another package in Golang

I have a custom AUTH package and there i have USER STRUCT.
So i want to import the auth package in my go project and override the struct or add new fields to the struct without modifying the package code.
package auth
type User struct {
gorm.Model
UserEmail string
UserPass string
}
Now i have main.go
package main
import "auth"
// WANT TO OVERRIDE OR EXTEND THE USER STRUCT
auth.User = {
UserAge string
}
function main() {
}
So i want to import the auth package in my go project and override the struct or add new fields to the struct without modifying the package code.
You simply cannot do this in Go. You have to redesign.
you can define a new type like this:
type NewUser struct {
auth.User
UserAge string
}

Golang Iris: Initialize parent controller's model to child controller's model

I understand that Go is not an object-oriented language but I'm trying to implement a inheritance structure in my Iris controllers as suggested by this article. My main motivation for doing so is to avoid repetition. So far, it has been working for me. Take a look at the following code for example.
// APIController.go (package Controllers)
type APIController struct {
mvc.C
}
func (c *APIController) Post(data map[string][]string) ([]byte, error) {
data_parsed := c.ParseFormData(data)
return json.Marshal(data_parsed)
}
// UserController.go (package Controllers)
type UserController struct {
mvc.C
*APIController
}
func (c *UserController) Post() ([]byte, error) {
return c.APIController.Post(c.Ctx.FormValues())
}
So far so good.
But I'm finding it difficult to replicate the same strategy for Models. This is what I've done so far
// Model.go (package Models)
type Model struct {
Id string `json:"_id"`
Created_at string `json:"created_at"`
Updated_at string `json:"updated_at"`
Deleted_at string `json:"deleted_at"`
}
// implements further set of functions to be used by 'child' models...
// User.go (package Models)
type User struct {
*Model
First_name string `json:"first_name"`
Last_name string `json:"last_name"`
Email string `json:"email"`
Username string `json:"username"`
Password string `json:"password"`
Last_login string `json:"last_login"`
}
// APIController.go (package Controllers)
type APIController struct {
mvc.C
Model Models.Model
}
// UserController.go (package Controllers)
type UserController struct {
mvc.C
*APIController
}
func (c *UserController) Post() ([]byte, error) {
c.APIController.Model = new(Models.User) //WRONG!
return c.APIController.Post(c.Ctx.FormValues())
}
As you can see, the APIController is expecting type Models.Model while UserController is passing *Models.User. The end goal is to have a generic model in APIController that any model from any controller and then is able to call all the functions defined in Models.Model so that I don't have to call those function everywhere.
Is it possible to do so? If not, what might be the best approach to avoid repeating the code?
Update
By using inheritance and single parent model and using that in parent APIController, I want to avoid replicating my filter/CRUD logic. For example, inside UserController, if I want to save a record, then instead of using User.Save(input_data) inside UserController, the Save should ideally be defined inside Models.Model and from APIController, I'm able to call Model.Save(input_data) rather than making the same call from child controllers individually.
First make Model an interface instead of a struct. Have it contain all methods that should be common to all models:
type Model interface {
// Common methods
}
Then, as long as User implements all those methods, you can have
c.APIController.Model = new(Models.User) // Now works!
One of the common methods could be Save. Otherwise make Save a non-method:
func Save(m Model) error {
...
}

Embedding model structs with same attribute names in golang

Using go 1.5, and gorm.
Say I want to make an events table that has a created_by_id and an updated_by_id columns.
I write my models like
type By struct {
ByID sql.NullInt64
By *User
}
type CreatedBy struct {
By
}
type UpdatedBy struct {
By
}
type Event struct {
CreatedBy
UpdatedBy
}
When I try to save an event object, the value for the column by_id will try to be saved rather than the values for created_by_id and updated_by_id. What do I need to do to make sure the column names of ByID attribute are different for CreatedBy and UpdatedBy?
The problem is that you're embedding both CreatedBy and UpdatedBy into Event, so calls to Event.By are ambiguous and not allowed (you'd have to be able to specify Event.CreatedBy.By and Event.UpdatedBy.By explicitly to disambiguate the two fields).
The solution, most likely, would be to not embed the types, but actually create a struct with explicit fields:
type Event struct {
CreatedBy CreatedBy
UpdatedBy UpdatedBy
}
gorm should now know how to disambiguate the two columns.
Of course if you're only going to embed By into CreatedBy and UpdatedBy for the purposes of column mapping then you shouldn't need to declare new structs:
type By struct {
ByID sql.NullInt64
By *User
}
type Event struct {
CreatedBy By
UpdatedBy By
}

Resources