You should never, ever mix the database layer with http layer. Or any other layer.
type Book struct {
ID uuid.UUID `db:"id" json:"id" validate:"required,uuid"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
UserID uuid.UUID `db:"user_id" json:"user_id" validate:"required,uuid"`
Title string `db:"title" json:"title" validate:"required,lte=255"`
Author string `db:"author" json:"author" validate:"required,lte=255"`
BookStatus int `db:"book_status" json:"book_status" validate:"required,len=1"`
BookAttrs BookAttrs `db:"book_attrs" json:"book_attrs" validate:"required,dive"`
}
db:"id" json:"id" <---- never do this.
Data that you use in JSON "objects" should never be mixed with Models "objects"
Those 2 things work in parallel universes, they should never have contact with each other. One thing is what an frontend application sends to you, another thing is what you put or get from the databases and another thing is what you return from the database and another thing is what you return to the user.
Except on really basic cases, like Todos and Hello worlds that data is always diferent. I advise to take a look at this awesome post: eltonminetto.dev/en/post/2020-07-0...
It explains in a lot more detail. Of course this does not affect simple applications. But as soon as you start having a few more complexities in your code, those "structs" will fail to provide you what you need.
A more concrete example of what I'm trying to explain would be:
if you signin up a user using email, password. would you use the same "struct" to map it to the database?
Does this has any relationship to what what you have in your "user(s)" table? Most likely your "user(s)" table has 15 fields.
Dont mix those.
PS: Also to mention, if you notice I named my struct with DTO (Data Transfer Object) usually is what is called to this kind of "objects" that you can pass arround to your services instead of passing multiple args to your methods.
Data that you use in JSON "objects" should never be mixed with Models "objects"
This is true for models like authorization or transactional models, where you really need to separate the JSON output through the REST API (as if for the user) and the database query layer (as if our internal).
For example, if we have a User structure where we define what will be output in the profile on the frontend, then it's logical that for the authorization process itself we would need to make a separate UserSignIn structure with just two fields of email and password. That's the only data we would go with a query to the database.
That's where I agree.
But the model in question in the article is a common example of outputting data "as is" after the query. So, I don't really understand why to break DRY and duplicate exactly the same structure in the database layer, if they are identical and were described only to show the principle of work itself?
Especially since there is no consensus on "how to do the structure correctly for Go projects". I adhere to the principle as described in this article, for such "dumb" models, so far I have not encountered a single problem in years of working with Go 🤷
I, by the way, will describe all such things "from the real world of Go development" in detail in my new series of articles Go Fiber by Examples on this blog.
Really good tutorial. Only one complain.
You should never, ever mix the database layer with http layer. Or any other layer.
db:"id" json:"id"<---- never do this.Data that you use in JSON "objects" should never be mixed with Models "objects"
Those 2 things work in parallel universes, they should never have contact with each other. One thing is what an frontend application sends to you, another thing is what you put or get from the databases and another thing is what you return from the database and another thing is what you return to the user.
Except on really basic cases, like Todos and Hello worlds that data is always diferent. I advise to take a look at this awesome post:
eltonminetto.dev/en/post/2020-07-0...
It explains in a lot more detail. Of course this does not affect simple applications. But as soon as you start having a few more complexities in your code, those "structs" will fail to provide you what you need.
A more concrete example of what I'm trying to explain would be:
if you signin up a user using email, password. would you use the same "struct" to map it to the database?
a struct for the payload would be something like:
Does this has any relationship to what what you have in your "user(s)" table? Most likely your "user(s)" table has 15 fields.
Dont mix those.
You service would be much cleaner if you pass:
MyAuthService(ctx context.Context, dto SignInDTO)instead of
MyAuthService(ctx context.Context, email, password string)Hi,
This is true for models like authorization or transactional models, where you really need to separate the JSON output through the REST API (as if for the user) and the database query layer (as if our internal).
For example, if we have a
Userstructure where we define what will be output in the profile on the frontend, then it's logical that for the authorization process itself we would need to make a separateUserSignInstructure with just two fields of email and password. That's the only data we would go with a query to the database.That's where I agree.
But the model in question in the article is a common example of outputting data "as is" after the query. So, I don't really understand why to break DRY and duplicate exactly the same structure in the database layer, if they are identical and were described only to show the principle of work itself?
Especially since there is no consensus on "how to do the structure correctly for Go projects". I adhere to the principle as described in this article, for such "dumb" models, so far I have not encountered a single problem in years of working with Go 🤷
I, by the way, will describe all such things "from the real world of Go development" in detail in my new series of articles Go Fiber by Examples on this blog.
Thanks for the comment, anyway! 👍
Another useful thing from dtos: