Handling optional boolean values - go

I'm failing to understand how I can work around the problem I'm experiencing in my own application.
Imagine this example of a struct that models an incoming request and a function that puts the fields from that request into a database.
type NewBooleanRequest struct {
RequiredString string `json:"requiredString"`
OptionalBoolean bool `json:"maybeBoolean"`
}
func LogBooleanRequest(req NewBooleanRequest, db *sql.DB) {
db.Exec("INSERT INTO log (booleanValue, stringValue) VALUES ($1, $2)", req.OptionalBoolean, req.RequiredString)
}
Now this obviously works fine if I know I will be given a value for all fields of my request model, but that's not a common requirement in reality. How do people generally model "optional" semantics for bool values given that bool has a zero value that is valid in essentially all contexts?

This question isn't specific to booleans, it's common for all NULLable types. The simplest solution is to use a pointer (*bool in your example). There are also Nullable values for common types provided by the sql package. sql.NullBool would be the one you want in this case.

Beside the accepted answer, I found this interesting library https://github.com/guregu/null that can deal with nullable value pretty well. It's very useful to declare API request params without messing with sql library on the server routing (which is not so relevant).
For your case, you can write your request like:
type NewBooleanRequest struct {
RequiredString string `json:"requiredString"`
OptionalBoolean null.Bool `json:"maybeBoolean"`
}
request := NewBooleanRequest {
RequiredString: "Your string",
OptionalBoolean: null.BoolFrom(false)
}
if request.OptionalBoolean.Valid {
fmt.Println(request.OptionalBoolean.Bool) // Print "false"
} else {
fmt.Println("request.OptionalBoolean is NULL")
}

Related

Workaround solution to avoid getters in Golang interface

Thank you for taking some time to read this question!
I'm new to Golang and I've been developing a simple social media API to practice the language in general. In this project I'm using a struct to represent the Model of a Post published by an user, as follows:
// models/post.go
package models
import "time"
type Post struct {
ID uint64
Title string
Content string
AuthorID uint64
Likes uint64
CreatedAt time.Time
}
func (p *Post) ValidateFields() error {
// validate fields
}
This post can be saved to the database with the help of a method that is inside a repository:
// repositories/posts.go
import (
"database/sql"
"models"
)
type PostsRepository struct {
db *sql.DB
}
func NewPostsRepository(db *sql.DB) *PostsRepository {
return &PostsRepository{db}
}
func (r *PostsRepository) Save(models.Post) (uint64, error) {
// Passing the model as a parameter
}
As you can see, the model is being passed as a parameter and that feels like a problem for two reasons:
I only need three fields to save the post to database (Title,
Content and AuthorID) because everything else will be generated
automatically
If I write an unit test to the Save function it will
rely on the model to work, therefore any problems with the model
would impact the test
So with that in mind I thought about changing the parameter from a model to an interface, but since interfaces only accept method signatures and in that specific case I only need attributes to save data on the database, I assume it would need a few getters such as:
type PostInterface interface {
GetTitle() string
GetContent() string
GetAuthorID() uint64
}
(I know it is not idiomatic to call a getter "GetAttribute", but it's just to give you an idea)
Due to that, I'd have to implement these three methods on my Post Model, which would look like
func (p Post) GetTitle() string {
return p.Title
}
func (p Post) GetContent() string {
return p.Content
}
func (p Post) GetAuthorID() uint64 {
return p.AuthorID
}
That doesn't look so good, but it gets worse when we go to the test.
Like I said, I do not want to use the model in the test so I would have to create a struct to serve as a stub or something that has only the three needed fields for the Save to work (which sounds good). However, I'd have to implement these three methods again so that the struct can be accepted as an interface by the Save function (which sounds bad)
It sounds like a lot of unecessary work, Is there any way to work around this? I'm not sure if I'm missing something conceptual about Go or if there are any changes on my architecture that could address to this issue, but I'm having trouble finding alternatives to this
Thank you!
Using a struct in the save function is perfectly fine and considered idiomatic. If this is just a data container I don't see any issues in testing this functionality. You could however opt for a slimmer version of the struct with just the respective fields you require when storing the content in the database.
For instance:
type Content struct {
Title string
Content string
AuthorID uint64
}
If you still want to decouple with an interface you can create a method on the Post model and return the Content struct, personally I don't see the need for this since it will not improve the testability and only increases complexity by using another layer of abstraction.
In your tests you can just create an instance of the Content struct and pass that to the Save function.

Go struct separation best practices

I am trying to figure out a decent approach toward dealing with multiple uses for a struct. Let me explain the scenario.
I have a struct that represents the Model in gorm. In the current implementation, I have validation bound to this struct so when a request hits the endpoint I would validate against the model's struct. This works fine for most cases. But then there are some instances where I want to have more control over the request and the response.
This is possible by introducing a few additional internal structs that will parse the request and response. And I can decouple the validation from the model into the request specific struct. I am trying to figure out what the best practice is around these patterns. Pretty sure a lot of peeps would have faced a similar situation.
// Transaction holds the transaction details.
type Transaction struct {
Program Program
ProgramID uuid.UUID
Type string
Value float64
Reference string
}
// TransactionRequest for the endpoint.
type TransactionRequest struct {
ProgramKey string `json:"program_key" validator:"required"`
Type string `json:"type" validator:"required,oneof=credit debit"`
Value float64 `json:"value" validator:"required,numeric"`
Reference string `json:"reference" validator:"required"`
}
Update:
I managed to find a balance by introducing additional tags for update requests, I wrote about how I achieved it here
I faced similar problem and for solving that, defined a method for validating and didn't use tags. I had to, because I follow DDD and we should validate in service layer not API layer.
here is a sample of my apporach:
type Station struct {
types.GormCol
CompanyID types.RowID `gorm:"not null;unique" json:"company_id,omitempty"`
CompanyName string `gorm:"not null;unique" json:"company_name,omitempty"`
NodeCode uint64 `json:"node_code,omitempty"`
NodeName string `json:"node_name,omitempty"`
Key string `gorm:"type:text" json:"key,omitempty"`
MachineID string `json:"machine_id,omitempty"`
Detail string `json:"detail,omitempty"`
Error error `sql:"-" json:"user_error,omitempty"`
Extra map[string]interface{} `sql:"-" json:"extra_station,omitempty"`
}
// Validate check the type of
func (p *Station) Validate(act action.Action) error {
fieldError := core.NewFieldError(term.Error_in_companys_form)
switch act {
case action.Save:
if p.CompanyName == "" {
fieldError.Add(term.V_is_required, "Company Name", "company_name")
}
if p.CompanyID == 0 {
fieldError.Add(term.V_is_required, "Company ID", "company_id")
}
}
if fieldError.HasError() {
return fieldError
}
return nil
}
file's address: https://github.com/syronz/sigma-mono/blob/master/model/station.model.go

How to omit some parameters of structure Gin gonic

I have big structure with more than 50 params
type Application struct {
Id int64 `json:"id"`
FullName string `json:"fullName,omitempty"`
ActualAddress string `json:"actualAddress,omitempty"`
.....
}
I use gin-gonic and when I return application I need to omit some params I've created a function which makes empty some params (playLink) and then gin returns me correct json (without unnecessary values). I heard that reflection isn't fast operation so in our case we can use a lot of ugly if-else or switch-cases. Is there any other solutions faster than reflecting and more beautiful than if-elses?
The thing is that structure params have non-empty values, so they wont by omitted by gin. That's why I've created function to make some params empty before return
The thing is, if you only want to zero a few fields, it's more readable to do it without a function, e.g.
app := Application{}
app.FullName, app.ActualAddress = "", ""
If you want to create a function for it, at least use variadic parameter, so it's easier to call it:
func zeroFields(application *Application, fields ...string) {
// ...
}
So then calling it:
zeroFields(&app, "FullName", "ActualAddress")
Yes, this will have to use reflection, so it's slower than it could be, and error prone (mistyped names can only be detected at runtime). If you want to avoid using reflection, pass the address of the fields:
func zeroFields(ps ...*string) {
for _, p := range ps {
*p = ""
}
}
This way you have compile-time guarantee that you type field names correctly, and that they have string type.
Calling it:
zeroFields(&application.FullName, &application.ActualAddress)
Try it on the Go Playground.
If I understand correctly: you want to return some values from your struct but not all of them? Perhaps a nested struct?
type Application struct {
ID struct {
ID int64 `json:"id"`
} `json:"id"`
Person struct {
Fullname string `json:"Fullname"
} `json:"person"
}
That should let you filter out the fields you want to use.

Golang proper use of interfaces

I am new to Go and am running into a situation that I am unsure how to solve. I am working on some code that takes a DNS packet in raw bytes and returns a struct called DNSPacket.
The struct looks like the following
type DNSPacket struct {
...some fields
Questions []Question
Answers []Answer
...some more fields
}
The issue I am having is with the Answers type which looks like this.
type Answer struct {
Name string
Type int
Class int
TTL uint32
RdLength int
Data []byte
}
Depending on the type of Answer the Data field must be decoded differently. For example if the Answer is an A record (Type 1) the data is simply an ipv4 address. However if the Answer is an SRV record (Type 33) then the data is contains port, priority, weight and target encoded in the byte slice.
I thought it would be great if I could have a method on Answer called DecodeData() that returns the correct data depending on the type, however since there is no overriding or inheritance in Go I am unsure how to solve this. I tried using an interface to solve this, but it would not compile. I tried something like
type DNSRecordType interface {
Decode(data []byte)
}
type RecordTypeSRV struct {
target string
...more fields
}
//to 'implement' the DNSRecordType interface
func (record *RecordTypeSRV) Decode(data []byte) {
//do the work to decode appropriately and set
//the fields on the record
}
Then in the Answer method
func (a *Answer) DecodeData() DNSRecordType {
if a.Type === SRVType {
record := RecordTypeSRV{}
record.Decode(a.Data)
return record
}
//do something similar for other record types
}
What would be the correct Go way of having a single Answer type, but be able to return different types of Answer Data depending on their type?
Sorry, if this is a completely beginner question as I am still very new to Go.
Thanks!
Let me summarize your question.
You have a DNS Packet with the list of Answers. Based on the type of answer you have to process the data in the answer.
type DNSPacket struct {
...some fields
Questions []Question
Answers []Answer
...some more fields
}
type Answer struct {
Name string
Type int
Class int
TTL uint32
RdLength int
Data []byte
}
Answer
Let's create an interface that should be implemented to process data.
type PacketProcessor interface {
Process(Answer)
}
Let SRV implements the PacketProcessor
type SRV struct {
...
}
func (s *SRV) Process(a Answer) {
...
}
Your processing logic should be as follows
func (a *Answer) Process() {
var p PacketProcessor
switch a.Type {
case SRVType:
p = &SRV{}
...
//other cases
}
//finally
p.Process(*a)
}
Hope it helps :).
There is a Gurgaon based golang community that is always ready to help developers with their problems.
You can join the community via slack
As I know, to return different types, the return param must be an interface. So you can simply declare the function like this:
func (a *Answer) DecodeData() (mode modeType, value interface{}) {}
mode means the value is A record or SRV record, and you can return anything you want with the value field.
The function caller can handle the value depending on mode
If you want the code be more elegant, you can define different value structs for each mode. Then the caller may act as below:
type modeType int
const (
ARecord modeType = 1
SRVRecord modeType = 2
)
switch mode {
case ARecord:
// do something
case SRVRecord:
// do something
}

When avoiding global vars (/state), i find myself linking objects backwards to its parent. Am I doing this right? if not explain why? and how-else?

Note: Im just picking the current struct/example to explain the problem.
type MsgBoxFactory struct{
db *dbSql //contains conn-pool and other DB related settings/flags
}
func (f *MsgBoxFactory) NewMsgBox(userId string) {
return MsgBox{userId, f.db} //f.db link is inevitable
}
type MsgBox struct {
ownerId string
db *dbSql
}
func (m *MsgBox) NewMessage(content string) *Message {
return Message{content, *m.dbSql} //m.dbSql link is inevitable
}
type Message struct {
content string
//other fields such as recipents, isRead, created time etc.
db *dbSql
}
func (m *Message) Send(to string) {
message.to = to //just imagine this saves the message to database.
m.db.Save(message)
}
I tend to call this "backward-referencing"[i don't know actual name]... Is this the only way? Previously i was "backward-referencing" entire parent objects. Now i find myself "backward-referencing" objects such as config/dbconn etc...
Is this a good way? what is better?
Oh i have also tried closure to get rid of it atleast from view.
type Message Struct{
content string
Send func(string) error // the problem is `json:"-"` needs to be added. Else the objects are not json compatible
}
func (m *MsgBox) NewMsg(content string) *Message {
msg := &Message{ content }
msg.Send = func(to string) error {
return m.db.Save(msg)
}
}
Basically the code looks almost equally cluttered with unnecessary complexity/code
EDIT: The question is not specific to go. Just posted it because i use go. Any tag suggestion is appreciated to open the question for wider community.
I usually implement a model helper relationship.
Where MsgBox is your model which has all the data specific elements (No DB related elements).
The MsgBoxHelper does all your database related work.
(i.e.
err := MsgBoxHelper.Save(MsgBox)
msgBox, err := MsgBoxHelper.Load(Key)
)
Edit:
The advantage with this method is it decouples your Model from the datastore, which should inturn make it easier should you wish to change your underlying technology (Which doesn't often happen). In practice it's more useful should you start doing things like caching.
If generically you are referencing other structures within your model i.e.
type MsgBox struct {
Colour *MsgBoxColour
...
}
type MsgBoxColor struct {
ID int
...
}
then when you load the Model in your MsgBoxHelper you call the MsgBoxColourHelper with the ID you stored in the MsgBoxColour table, this then returns your MsgBoxColour that you then associate with the returning MsgBox.

Resources