Get length of nullable string - go

I have the following structure:
type NetAuth struct {
Identificator *string `json:"identificator"`
Password *string `json:"password"`
DeviceID *string `json:"deviceId"`
Type int `json:"type"`
}
I am trying to get the length of Identificator with len(event.Identificator) however I get Invalid argument for len
Before calling len I check if it's nil. I am coming from Java/C#/PHP background and it's my first time writing in GO.

There is no simple len(string) concept in Go. You either need the number of bytes in the string representation or the number of characters (so called runes). For ASCII strings both values are the same while for unicode-encoded strings they are usually different.
import "unicode/utf8"
// Firt check that the pointer to your string is not nil
if nil != event.Identificator {
// For number of runes:
utf8.RuneCountInString(*event.Identificator)
// For number of bytes:
len(*event.Identificator)
}
For more information you can check this answer https://stackoverflow.com/a/12668840/1201488.
UPD: event.Identificator is a pointer to a string value in the NetAuth structure rather than a string value. So you need to dereference it first via *event.Identificator.

You are using a pointer, so try this:
println(len(*vlr.Identificator))
For example,
package main
import (
//"fmt"
"encoding/json"
"strings"
"io"
)
type NetAuth struct {
Identificator *string `json:"identificator"`
Password *string `json:"password"`
DeviceID *string `json:"deviceId"`
Type int `json:"type"`
}
func jsondata() io.Reader {
return strings.NewReader(`{"identificator": "0001", "password": "passkey"}`)
}
func main() {
dec := json.NewDecoder(jsondata())
vlr := new(NetAuth)
dec.Decode(vlr)
println(*vlr.Identificator)
println(len(*vlr.Identificator))
}
Playground: https://play.golang.org/p/duf0tEddBsR
Output:
0001
4

Related

Difference in string and *string in Gorm model declaration

The docs of gorm https://gorm.io/docs/models.html present an example below.
The field Name and Email are described with string and *string.
What is the main difference here?
Also how to provide the datatype for the images field storing a list of images link?
Should it be []string or []*string?
type User struct {
ID uint
Name string
Email *string
Images []string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
Go has default values for every primitive data types.
int -> 0, string -> "", bool -> false likewise. So if you need to add null value, or load null value to a variable, it should be a pointer. Otherwise it is defaulted.
Default value of a pointer is nil in Go.
And complex data types such as slices, maps keep references. So their default value is nil. So, Images []string here images can be nil.
Below code with pointer types User1 and without pointer types User2 show the difference in default values.
package main
import (
"fmt"
"time"
)
type User1 struct {
Email *string
Images []string
Birthday *time.Time
}
type User2 struct {
Email string
Images []string
Birthday time.Time
}
func main() {
user1 := User1{}
user2 := User2{}
fmt.Printf("user1 := %+v \n", user1)
//Output : user1 := {Email:<nil> Images:[] Birthday:<nil>}
fmt.Printf("user2 := %+v \n", user2)
//Output : user2 := {Email: Images:[] Birthday:0001-01-01 00:00:00 +0000 UTC}
}
The main difference is that if you use pointers, you can put a null value into the DB, else you must put a string.
Esentially if the database field is nullable, you should use pointers.

Printing value of a *big.Int field in a Go struct

I have a big.Int I need to store inside of a struct, but when I try to do so it overflows. Code example below
type NumberStore struct {
mainnumber *big.Int
}
var ledger NumberStore
// In decimal this is 33753000000000000000
var largehex string = "1D46ABEAB3FC28000"
myNumber := new(big.Int)
myNumber.SetString(largehex, 16)
ledger.mainnumber = myNumber
fmt.Println(ledger)// Prints 0xc0000a64c0, but I need it to be 33753000000000000000
Since mainnumber is a pointer field in your NumberStore struct, printing out the struct by default will just print out the value of the pointer, not the value it points to.
As the comment says, if you make your field exported then fmt.Println will show the underlying value; but if you don't need it exported, then fmt.Println(ledger.mainnumber) should print the number you expect. Here's your full code with one line added at the end:
package main
import (
"fmt"
"math/big"
)
type NumberStore struct {
mainnumber *big.Int
}
func main() {
var ledger NumberStore
// In decimal this is 33753000000000000000
var largehex string = "1D46ABEAB3FC28000"
myNumber := new(big.Int)
myNumber.SetString(largehex, 16)
ledger.mainnumber = myNumber
fmt.Println(ledger)
fmt.Println(ledger.mainnumber)
}
Run on the Playground, it prints:
{0xc000092000}
33753000000000000000
By printing like this fmt.Println(ledger), you're relying on the default formatting of the value ledger. For each field in the struct, it will only print the default representation of that value, unless it can access the appropriate custom formatting code for that type. For mainnumber of type *big.Int, that is "pointer to big.Int", it's simply printing the pointer address.
In order to give fmt access to the custom string formatting code for a *big.Int value, you either need to pass it directly: fmt.Println(ledger.mainnumber), or change mainnumber to an exported field, like this:
type NumberStore struct {
Mainnumber *big.Int
}
The fmt package cannot automatically find the value's formatting code (the .String() string method) if it is an unexported struct field.

How to access to a struct parameter value from a variable in Golang

I'm trying to access to a struct properties with a variable who contains the property key.
For example, i got this struct :
type person struct {
name string
age int
}
I have a variable "property" who contain a string value "age".
I would like to access to the age with something like person.property ?
Do you think it is possile in golang ?
If you're looking for something like person[property] like you do in Python or JavaScript, the answer is NO, Golang does not support dynamic field/method selection at runtime.
But you can do it with reflect:
import (
"fmt"
"reflect"
)
func main() {
type person struct {
name string
age int
}
v := reflect.ValueOf(person{"Golang", 10})
property := "age"
f := v.FieldByName(property)
fmt.Printf("Person Age: %d\n", f.Int())
}

How can I set null value as default to struct

I am trying to add null value as default to struct. Is there any way to add null as default?
type Values struct {
FirstValue string `default:"My First Value"`
SecondValue string `default:nil` // something like that
}
Strings in Go cannot be nil. Their zero value is just an empty string - "".
See https://tour.golang.org/basics/12
Also, there is no default tag in Go as each type has a zero value which is used as a "default". But, there are patterns in Go that allow you to set different "default" values, see How to set default values in Go structs.
In Go you can't access uninitialized memory. If you don't provide an initial value in a variable declaration, the variable will be initialized to the zero value of its type automatically.
Moreover, you can't define default values for struct fields. Unless given with a composite literal, all fields will get their zero values.
Zero value of the string type is the empty string "". If you need to store the null value, use a pointer to string. Zero value for pointers is nil:
type Values struct {
FirstValue string
SecondValue *string
}
maybe try this way :)
package main
import (
"encoding/json"
"fmt"
)
type Hoho struct {
Name *string `json:"name"`
}
func main() {
var nama string = "ganang"
var h Hoho
h.Name = NullString(nama)
wo, _ := json.Marshal(h)
fmt.Print(string(wo))
}
func NullString(v string) *string {
if v == "" {
return nil
}
return &v
}

Cannot convert time.Now() to a string

I have this struct:
// Nearby whatever
type Nearby struct {
id int `json:"id,omitempty"`
me int `json:"me,omitempty"`
you int `json:"you,omitempty"`
contactTime string `json:"contactTime,omitempty"`
}
and then I call this:
strconv.Itoa(time.Now())
like so:
s1 := Nearby{id: 1, me: 1, you: 2, contactTime: strconv.Itoa(time.Now())}
but it says:
> cannot use time.Now() (type time.Time) as type int in argument to
> strconv.Itoa
does anyone know what that's about? I am trying to convert an int to a string here.
does anyone know what that's about? I am trying to convert an int to a string here.
Time type is not equivalent to an int. If your need is a string representation, type Time has a String() method.
Sample code below (also available as a runnable Go Playground snippet):
package main
import (
"fmt"
"time"
)
// Nearby whatever
type Nearby struct {
id int
me int
you int
contactTime string
}
func main() {
s1 := Nearby{
id: 1,
me: 1,
you: 2,
contactTime: time.Now().String(), // <-- type Time has a String() method
}
fmt.Printf("%+v", s1)
}
Hope this helps. Cheers,

Resources