Cannot convert time.Now() to a string - go

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,

Related

How to omit conditional field of struct within marshal

There is struct of MyStruct.
type MyStruct struct {
Code int `json:"Code"`
Flags uint8 `json:"Flags"`
OptionField int `json:",omitempty"`
}
Following code convert it to json.
f := MyStruct{Code:500, OptionField:41}
r, _ := json.Marshal(f)
fmt.Println(string(r)
I need to "OptionField" be optional. Some time it should exist in json with one of values [0, 1, 2, 3, ]. and in the other time it should exclude from json.
My problem is: omitempty will exclude it when the value is zero, and the default value of int is zero. Is there any way to omit field in condition (ex: omit if value is -1). Or there is any way to do it.
You could use *int instead of int and set the pointer value to nil in order to omit this.
package main
import (
"encoding/json"
"fmt"
)
type MyStruct struct {
Code int `json:"Code"`
Flags uint8 `json:"Flags"`
OptionField *int `json:",omitempty"`
}
func format(s MyStruct) string {
r, _ := json.Marshal(s)
return string(r)
}
func main() {
f := MyStruct{Code: 500, Flags: 10, OptionField: new(int)}
fmt.Println(format(f)) // {"Code":500,"Flags":10,"OptionField":0}
f.OptionField = nil
fmt.Println(format(f)) // {"Code":500,"Flags":10}
}

Get length of nullable string

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

Golang: convert struct to embedded at offset 0 struct

I have some different structs like Big with Small embedded at offset 0.
How can I access Small's structure fields from code, that doesn't know anything about Big type, but it is known that Small is at offset 0?
type Small struct {
val int
}
type Big struct {
Small
bigval int
}
var v interface{} = Big{}
// here i only know about 'Small' struct and i know that it is at the begining of variable
v.(Small).val // compile error
It seems that compiler is theoretically able to operate such expression, because it knows that Big type has Small type embedded at offset 0. Is there any way to do such things (maybe with unsafe.Pointer)?
While answer with reflection is working but it has performance penalties and is not idiomatic to Go.
I believe you should use interface. Like this
https://play.golang.org/p/OG1MPHjDlQ
package main
import (
"fmt"
)
type MySmall interface {
SmallVal() int
}
type Small struct {
val int
}
func (v Small) SmallVal() int {
return v.val
}
type Big struct {
Small
bigval int
}
func main() {
var v interface{} = Big{Small{val: 3}, 4}
fmt.Printf("Small val: %v", v.(MySmall).SmallVal())
}
Output:
Small val: 3
Avoid using unsafe whenever possible. The above task can be done using reflection (reflect package):
var v interface{} = Big{Small{1}, 2}
rf := reflect.ValueOf(v)
s := rf.FieldByName("Small").Interface()
fmt.Printf("%#v\n", s)
fmt.Printf("%#v\n", s.(Small).val)
Output (try it on the Go Playground):
main.Small{val:1}
1
Notes:
This works for any field, not just the first one (at "offset 0"). This also works for named fields too, not just for embedded fields. This doesn't work for unexported fields though.
type Small struct {
val int
}
type Big struct {
Small
bigval int
}
func main() {
var v = Big{Small{10},200}
print(v.val)
}

generic function to get size of any structure in Go

I am writing a generic function to get the size of any type of structure, similar to sizeof function in C.
I am trying to do this using interfaces and reflection but I'm not able to get the correct result. Code is below:
package main
import (
"fmt"
"reflect"
"unsafe"
)
func main() {
type myType struct {
a int
b int64
c float32
d float64
e float64
}
info := myType{1, 2, 3.0, 4.0, 5.0}
getSize(info)
}
func getSize(T interface{}) {
v := reflect.ValueOf(T)
const size = unsafe.Sizeof(v)
fmt.Println(size)
}
This code returns wrong result as 12. I am very new to Go, kindly help me on this.
You're getting the size of the reflect.Value struct, not of the object contained in the interface T. Fortunately, reflect.Type has a Size() method:
size := reflect.TypeOf(T).Size()
This gives me 40, which makes sense because of padding.
Go 1.18
With Go 1.18 you can use a generic function with unsafe.Sizeof:
func getSize[T any]() uintptr {
var v T
return unsafe.Sizeof(v)
}
Note that this will be more performant than using reflect, but it will introduce unsafe in your code base — some static analysis tools may give warnings about that.
However if your goal is to improve code reuse or get sizes at run time (read on for the solution to that), this won't help much because you still need to call the function with proper instantiation:
type myType struct {
a int
b int64
c float32
d float64
e float64
}
func main() {
fmt.Println(getSize[myType]())
}
You might get the most out of this when used as part of some other generic code, e.g. a generic type or function where you pass a type param into getSize. Although if you have the argument v this is equivalent to calling unsafe.Sizeof(v) directly. Using a function could be still useful to hide usage of unsafe. A trivial example:
func printSize[T any](v T) {
// (doing something with v)
// instantiate with T and call
s := getSize[T]()
// s := unsafe.Sizeof(v)
fmt.Println(s)
}
Otherwise you can pass an actual argument to getSize. Then type inference will make it unnecessary to specify the type param. This code perhaps is more flexible and allows you to pass arbitrary arguments at runtime, while keeping the benefits of avoiding reflection:
func getSize[T any](v T) uintptr {
return unsafe.Sizeof(v)
}
func main() {
type myType struct {
a int
b int64
c float32
d float64
e float64
}
info := myType{1, 2, 3.0, 4.0, 5.0}
// inferred type params
fmt.Println(getSize(info)) // 40
fmt.Println(getSize(5.0)) // 8
fmt.Println(getSize([]string{})) // 24
fmt.Println(getSize(struct {
id uint64
s *string
}{})) // 16
}
Playground: https://go.dev/play/p/kfhqYHUwB2S

What's the difference between new(Struct) and &Struct{} in Go?

They seem to be the same:
package main
import "fmt"
type S struct {
i int
}
func main() {
var s1 *S = new(S)
fmt.Println(s1)
var s2 *S = &S{}
fmt.Println(s2) // Prints the same thing.
}
Update:
Hm. I just realized that there's no obvious way to initialize S.i using new. Is there a way to do that? new(S{i:1}) does not seem to work :/
From Effective Go:
As a limiting case, if a composite literal contains no fields at all, it creates a zero value for the type. The expressions new(File) and &File{} are equivalent.
Not only do they give the same resulting value, but if we allocate something both ways and look at their values...
// Adapted from http://tour.golang.org/#30
package main
import "fmt"
type Vertex struct {
X, Y int
}
func main() {
v := &Vertex{}
v2 := new(Vertex)
fmt.Printf("%p %p", v, v2)
}
...we'll see that they are in fact allocated in consecutive memory slots. Typical output: 0x10328100 0x10328108. I'm not sure if this is an implementation detail or part of the specification, but it does demonstrate that they're both being allocated from the same pool.
Play around with the code here.
As for initializing with new, according to the language spec: The built-in function new takes a type T and returns a value of type *T. The memory [pointed to] is initialized as described in the section on initial values. Because functions in go can't be overloaded, and this isn't a variadic function, there's no way to pass in any initialization data. Instead, go will initialize it with whatever version of 0 makes sense for the type and any member fields, as appropriate.
Case 1: package main
import (
"fmt"
)
type Drink struct {
Name string
Flavour string
}
func main() {
a := new(Drink)
a.Name = "Maaza"
a.Flavour = "Mango"
b := a
fmt.Println(&a)
fmt.Println(&b)
b.Name = "Frooti"
fmt.Println(a.Name)
}//This will output Frooti for a.Name, even though the addresses for a and b are different.
Case 2:
package main
import (
"fmt"
)
type Drink struct {
Name string
Flavour string
}
func main() {
a := Drink{
Name: "Maaza",
Flavour: "Mango",
}
b := a
fmt.Println(&a)
fmt.Println(&b)
b.Name = "Froti"
fmt.Println(a.Name)
}//This will output Maaza for a.Name. To get Frooti in this case assign b:=&a.

Resources