This question already has answers here:
How to set default values in Go structs
(11 answers)
Closed 5 years ago.
I want to assign default value for struct field in Go. I am not sure if it is possible but while creating/initializing object of the struct, if I don't assign any value to the field, I want it to be assigned from default value. Any idea how to achieve it?
type abc struct {
prop1 int
prop2 int // default value: 0
}
obj := abc{prop1: 5}
// here I want obj.prop2 to be 0
This is not possible. The best you can do is use a constructor method:
type abc struct {
prop1 int
prop2 int // default value: 0
}
func New(prop1 int) abc {
return abc{
prop1: prop1,
prop2: someDefaultValue,
}
}
But also note that all values in Go automatically default to their zero value. The zero value for an int is already 0. So if the default value you want is literally 0, you already get that for free. You only need a constructor if you want some default value other than the zero value for a type.
Related
This question already has answers here:
Golang embedded struct type
(3 answers)
Closed 2 years ago.
Within a go package named kubesecretsPkg I declare the following two struct types:
type KubesecretsOpts struct {
FullPathToRepo string
FullPathToApp string
}
type KubesecretsSetOpts struct {
KubesecretsOpts
Variable string
Value string
}
I am trying to initialise an outer (KubesecretsSetOpts) in another package as follows:
kSetOpts := kubesecretsPkg.KubesecretsSetOpts{
kubesecretsPkg.KubesecretsOpts: {
FullPathToRepo: fullPathToRepo,
FullPathToApp: fullPathToApp,
},
Variable: variable,
Value: value,
}
this fails as follows:
Why am I not able to directly initialise an embedded struct?
The right syntax would be
kSetOpts := kubesecretsPkg.KubesecretsSetOpts{
KubesecretsOpts: kubesecretsPkg.KubesecretsOpts{
FullPathToRepo: fullPathToRepo,
FullPathToApp: fullPathToApp,
},
Variable: variable,
Value: value,
}
name of the field in the struct is "KubesecretsOpts" even in this scope however the type of the field is kubesecretsPkg.KubesecretsOpts. You are getting "invalid field name" error due to former fact in this scope.
I'm trying to normalize data from a number of sources. One of those sources is JSON with a nullable ID.
type Entry struct {
ID *int // Can be null
}
What's Go's idiomatic way to deal with a nullable ID, where the number 0 might be a valid ID? I'm torn between what I see as three options.
Do I normalize by passing possibly-nil pointer around?
type NormalizedEntry struct {
ID *int
}
Do I add a separate HasID property?
type NormalizedEntry struct {
HasID bool
ID int
}
Do I pass -1 instead of 0 to represent the "zero value"? (Like how strings.Index returns -1 if a value is not found)
type NormalizedEntry struct {
ID int
}
Or is there some other, better, method that I'm not yet aware of?
Say we have a struct like so:
type Foo struct {
one string
two int
}
is it possible to declare literal values for this, something like:
type Foo struct {
one "foobar"
two int
}
or
type Foo struct {
one string
two 5678
}
basically for some objects we might have a hardcoded value for a field.
No, Go does not support literal types (a la TypeScript). Moreover, it actually can't, because of zero values.
Every type has a zero value which always exists and is always assignable to it. When variables of a type are declared, they are implicitly assigned to their type's zero value.
For integer (int, uint, int32, uint32, int64, uin64) or float (float32, float64) or complex (complex64 or complex128) types, this is just 0 (0.0 respectively).
For string types, this is the empty string "".
For slices, maps, pointers, channels, and interfaces, the zero value is nil.
For arrays (not slices: arrays are value-types with statically-known length); their zero value is just the zero value of the element type repeated to fill every slot
The zero value of a struct type is a struct all of whose fields are zero values
In any case, because it is always possible for any type to have a zero value, it would be incompatible to create a type which only allows for any particular non-zero value.
The best a literal type "foo" could possibly represent is that the value is either "foo" or the zero value "" (and no, Go doesn't support this anyway).
The closest you'll be able to do is a constant declaration, or a receiver function that just-so-happens to return a fixed value instead of an actual field.
Go is statically typed language, meaning every variable need to be declared with specific data type.
Setting default value for each fields inside a struct on declaration is not possible in Go. it's not supported.
But maybe you can do something like this.
type Foo struct {
one string
two int
}
func NewFoo() *Foo {
foo := new(Foo)
foo.one = "default value for one"
foo.two = 2
return foo
}
func main() {
objectWithDefaultValueForItsField := NewFoo()
}
What I did is basically just created a function with name isNew<struct name>(). This function returns a new object with default value for each of the fields defined.
Notable exception, for object that created from anonymous struct, the default value of the fields can be specified on declaration. i.e.
obj := struct {
one string
two int
}{
"default value for one",
2,
}
This question already has answers here:
How to update map values in Go
(3 answers)
Closed 4 years ago.
Does anyone have any idea why this doesn't work?
I've been racking my brain for about 4 hours now. I cannot make it work.
In my opinion, I'm trying to do the same thing twice. I'm making a map of a field in a struct, and then I'm doing it again on another field in a different struct.
If I try to make the map. It fails with: "cannot assign to struct field. Bet.Events["one"].Runners in map".
So if I remove the make, and just try to assign it, I get: "assignment to entry in nil map"
https://play.golang.org/p/kRcXoyO-8FN
var Bet BetStruct
type BetStruct struct {
Events map[string]Event
}
type Event struct {
Name string
Runners map[int]Runner
}
type Runner struct {
Name string
}
func main(){
// == THIS WORKS FINE ==
Bet.Events = make(map[string]Event)
Bet.Events["one"] = Event{
Name: "first",
}
Bet.Events["two"] = Event{
Name: "second",
}
// == THIS DOES NOT WORK ==
Bet.Events["one"].Runners = make(map[int]Runner)
Bet.Events["one"].Runners[0] = Runner{
Name: "Jeff",
}
}
The default value for map is nil (before or without make(map))
You set a default value for Runners in this code:
Bet.Events["one"] = Event{
Name: "first",
}
So, Runners wasn't defined clearly and was setting to nil.
Structs are mutable except map elements. (From below comment of #icza: "Structs are modifiable. It's values stored in map that are not modifiable, because values stored in a map are not addressable.")
You cannot reinitialize map element Bet.Events["one"] because is not addressable.
You need to do:
Bet.Events["one"] = Event{
Name: "first",
Runners: make(map[int]Runner),
}
Thanks #icza for marking errors in the text
This question already has answers here:
How to set bool pointer to true in struct literal?
(5 answers)
Closed 11 months ago.
type MyStruct struct {
IsEnabled *bool
}
How do I change value of *IsEnabled = true
None of these work:
*(MyStruct.IsEnabled) = true
*MyStruct.IsEnabled = true
MyStruct.*IsEnabled = true
You can do this by storing true in a memory location and then accessing it as seen here:
type MyStruct struct {
IsEnabled *bool
}
func main() {
fmt.Println("Hello, playground")
t := true // Save "true" in memory
m := MyStruct{&t} // Reference the location of "true"
fmt.Println(*m.IsEnabled) // Prints: true
}
From the docs:
Named instances of the boolean, numeric, and string types are
predeclared. Composite types—array, struct, pointer, function,
interface, slice, map, and channel types—may be constructed using type
literals.
Since boolean values are predeclared, you can't create them via a composite literal (they're not composite types). The type bool has two const values true and false. This rules out the creation of a literal boolean in this manner: b := &bool{true} or similar.
It should be noted that setting a *bool to false is quite a bit easier as new() will initialize a bool to that value. Thus:
m.IsEnabled = new(bool)
fmt.Println(*m.IsEnabled) // False