How can I set null value as default to struct - go

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
}

Related

Is there a way to set a pointer struct field to a pointer pointing to the Zero value of that pointer type using reflect?

That was a mouthful of a title, let me explain more. Assuming I have a struct of all pointers (don't know of what type)
type A struct {
S *string
I *int
}
I want to write a function that takes a pointer to that struct and given a fieldName sets that field to a pointer to the Zero/empty value of that pointer. For example:
func setZeroForField(i any, fieldName string) {
// do stuff
}
a := A{}
setZeroForField(&a, "S")
setZeroForField(&a, "I")
// *a.S == ""
// *a.I == 0
Is there any way to do it using reflect? I know how to get the types of the fields of A but I can't use reflect.Indirect because it just returns a Zero value which in this case is a nil pointer, not the empty string or 0.
func setZeroForField(i any, fieldName string) {
rv := reflect.ValueOf(i).Elem()
fv := rv.FieldByName(fieldName)
fv.Set(reflect.New(fv.Type().Elem()))
}
https://go.dev/play/p/7clmztF5uaa

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.

Casting pointer value expression

I'm trying to figure out what this expression does:
(*levelValue)(&level)
I don't understand what is happening, it seems like it dereferencing levelValue first, but not sure why as the type of levelValue is int32
Some context below
import "flag"
type Level int32
type levelValue Level
// LevelFlag defines a Level flag with specified name, default value and
// usage string. The return value is the address of a Level value that stores
// the value of the flag.
func LevelFlag(name string, defaultLevel Level, usage string) *Level {
level := defaultLevel
flag.Var((*levelValue)(&level), name, usage)
return &level
}
func (l *levelValue) Set(s string) error {
return (*Level)(l).UnmarshalText([]byte(s))
}
func (l *levelValue) String() string {
return (*Level)(l).String()
}
Reference
This is a type conversion:
When you define a type like that
type A B
You can convert a variable of type B to type A like that:
b := B
a := A(b)
In your case, the type A is (*levelValue) (The parenthesis are needed to specify that the type is a pointer to a levelValue. And the variable b is &level (A pointer that points to the variable level)

What is the default value of a map of struct

What is the default value of struct in a map? How to check the map value is initialized?
type someStruct struct {
field1 int
field2 string
}
var mapping map[int]someStruct
func main() {
mapping := make(map[int]someStruct)
}
func check(key int) {
if mapping[key] == ? {}
}
Should I check against nil or someStruct{}?
Default value of a struct is zero value for each field which is different on basis of its type.
When storage is allocated for a variable, either through a
declaration or a call of new, or when a new value is created, either
through a composite literal or a call of make, and no explicit
initialization is provided, the variable or value is given a default
value. Each element of such a variable or value is set to the zero
value for its type: false for booleans, 0 for numeric types, "" for
strings, and nil for pointers, functions, interfaces, slices,
channels, and maps. This initialization is done recursively, so for
instance each element of an array of structs will have its fields
zeroed if no value is specified.
type T struct { i int; f float64; next *T }
t := new(T)
the following holds:
t.i == 0
t.f == 0.0
t.next == nil
But for checking the value of a map based on the key if it exists you can use it as:
i, ok := m["route"]
In this statement, the first value (i) is assigned the value stored under the key "route". If that key doesn't exist, i is the value type's zero value (0). The second value (ok) is a bool that is true if the key exists in the map, and false if not.
For your question
Should I check against nil or someStruct{} ?
To check for initialized empty struct you can check for someStruct{} as:
package main
import (
"fmt"
)
type someStruct struct {
field1 int
field2 string
}
var mapping map[int]someStruct
func main() {
var some someStruct
fmt.Println(some == (someStruct{}))
//mapping := make(map[int]someStruct)
}
Go playground

Using reflect, how do you set the value of a struct field?

having a rough time working with struct fields using reflect package. in particular, have not figured out how to set the field value.
type t struct { fi int; fs string }
var r t = t{ 123, "jblow" }
var i64 int64 = 456
getting Name of field i - this seems to work
var field = reflect.TypeOf(r).Field(i).Name
getting value of field i as a) interface{}, b) int - this seems to work
var iface interface{} = reflect.ValueOf(r).Field(i).Interface()
var i int = int(reflect.ValueOf(r).Field(i).Int())
setting value of field i - try one - panic
reflect.ValueOf(r).Field(i).SetInt( i64 )
panic: reflect.Value·SetInt using value obtained using unexported field
assuming it did not like field names "id" and "name", so renamed to "Id" and "Name"
a) is this assumption correct?
b) if correct, thought not necessary since in same file / package
setting value of field i - try two (with field names capitalized ) - panic
reflect.ValueOf(r).Field(i).SetInt( 465 )
reflect.ValueOf(r).Field(i).SetInt( i64 )
panic: reflect.Value·SetInt using unaddressable value
Instructions below by #peterSO are thorough and high quality
Four. this works:
reflect.ValueOf(&r).Elem().Field(i).SetInt( i64 )
he documents as well that the field names must be exportable (begin with capital letter)
The Go json package marshals and unmarshals JSON from and to Go structures.
Here's a step-by-step example which sets the value of a struct field while carefully avoiding errors.
The Go reflect package has a CanAddr function.
func (v Value) CanAddr() bool
CanAddr returns true if the value's
address can be obtained with Addr.
Such values are called addressable. A
value is addressable if it is an
element of a slice, an element of an
addressable array, a field of an
addressable struct, or the result of
dereferencing a pointer. If CanAddr
returns false, calling Addr will
panic.
The Go reflect package has a CanSet function, which, if true, implies that CanAddr is also true.
func (v Value) CanSet() bool
CanSet returns true if the value of v
can be changed. A Value can be changed
only if it is addressable and was not
obtained by the use of unexported
struct fields. If CanSet returns
false, calling Set or any
type-specific setter (e.g., SetBool,
SetInt64) will panic.
We need to make sure we can Set the struct field. For example,
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
// N at start
fmt.Println(n.N)
// pointer to struct - addressable
ps := reflect.ValueOf(&n)
// struct
s := ps.Elem()
if s.Kind() == reflect.Struct {
// exported field
f := s.FieldByName("N")
if f.IsValid() {
// A Value can be changed only if it is
// addressable and was not obtained by
// the use of unexported struct fields.
if f.CanSet() {
// change value of N
if f.Kind() == reflect.Int {
x := int64(7)
if !f.OverflowInt(x) {
f.SetInt(x)
}
}
}
}
}
// N at end
fmt.Println(n.N)
}
Output:
42
7
If we can be certain that all the error checks are unnecessary, the example simplifies to,
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
fmt.Println(n.N)
reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7)
fmt.Println(n.N)
}
BTW, Go is available as open source code. A good way to learn about reflection is to see how the core Go developers use it. For example, the Go fmt and json packages. The package documentation has links to the source code files under the heading Package files.
This seems to work:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
Number int
Text string
}
func main() {
foo := Foo{123, "Hello"}
fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))
reflect.ValueOf(&foo).Elem().Field(0).SetInt(321)
fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))
}
Prints:
123
321

Resources