What is the purpose of a field named "_" (underscore) containing an empty struct? - go

I've seen two pieces of Go code using this pattern:
type SomeType struct{
Field1 string
Field2 bool
_ struct{} // <-- what is this?
}
Can anyone explain what this code accomplishes?

This technique enforces keyed fields when declaring a struct.
For example, the struct:
type SomeType struct {
Field1 string
Field2 bool
_ struct{}
}
can only be declared with keyed fields:
// ALLOWED:
bar := SomeType{Field1: "hello", Field2: true}
// COMPILE ERROR:
foo := SomeType{"hello", true}
One reason for doing this is to allow additional fields to be added to the struct in the future without breaking existing code.

Related

Golang _ struct {} inside a struct. Whats the purpose of it? [duplicate]

I've seen two pieces of Go code using this pattern:
type SomeType struct{
Field1 string
Field2 bool
_ struct{} // <-- what is this?
}
Can anyone explain what this code accomplishes?
This technique enforces keyed fields when declaring a struct.
For example, the struct:
type SomeType struct {
Field1 string
Field2 bool
_ struct{}
}
can only be declared with keyed fields:
// ALLOWED:
bar := SomeType{Field1: "hello", Field2: true}
// COMPILE ERROR:
foo := SomeType{"hello", true}
One reason for doing this is to allow additional fields to be added to the struct in the future without breaking existing code.

How do I make sure that the fileds of the root struct get parsed first and then the fields of embedded struct gets parsed

I have the struct as follows:-
type Inner struct {
FooInner string `json:"fooInner"`
BarInner string `json:"barInner,omitempty"`
}
type Root struct {
Inner
Foo string `json:"foo"`
Bar string `json:"bar"`
}
I want the fields of "Root" struct to be parsed first and then the fields of the "Inner" struct. But here the fields of Inner struct is getting parsed first.
If you are asking about JSON marshaling (which is not parsing) and want fields marshaled in a certain order, a marshaler will typically marshal fields in their index order & recurse any embedded structs along the way. Struct field indices - as seen by the reflect package that json.Marhsal uses - are defined by their order of appearance in your code.
So put the fields you want first - and any embedded structs later:
type Root struct {
Foo string `json:"foo"`
Bar string `json:"bar"`
Inner // <- move this last
}
Playground Example
b, _ := json.Marshal(Root{})
{"foo":"","bar":"","fooInner":""}

Using (sub)struct located in other package in Datastore

I haven't been able to find any information related to this.. let's say you call an API and save the resulted json into a struct in package Foo, like this:
package foo
type FooData struct {
A string `json:"c"`
B int `json:"c"`
C int64 `json:"c"`
}
Then you have your own model package:
package bar
import (
"github.com/bla/bla/foo"
)
type BarData struct {
A float
Foo foo.FooData
}
Is this possible? Is there anything negative about doing it this way? The reason is the structs are over a hundred lines, so I feel it would be wasteful to duplicate it.
Also, what if I only want to index in B? Then I can just change it to:
type FooData struct {
A string `datastore:",noindex" `json:"c"`
B int `json:"c"`
C int64 `datastore:",noindex" `json:"c"`
}
?
Edit: Just to make it clear, my intention is to save the BarData struct in Datastore
The Go Datastore package has some documentation relating to this - https://cloud.google.com/appengine/docs/standard/go/datastore/reference#hdr-Structured_Properties
"Structured Properties
If the struct pointed to contains other structs, then the nested or embedded structs are flattened. For example, given these definitions:
type Inner1 struct {
W int32
X string
}
type Inner2 struct {
Y float64
}
type Inner3 struct {
Z bool
}
type Outer struct {
A int16
I []Inner1
J Inner2
Inner3
}
then an Outer's properties would be equivalent to those of:
type OuterEquivalent struct {
A int16
IDotW []int32 `datastore:"I.W"`
IDotX []string `datastore:"I.X"`
JDotY float64 `datastore:"J.Y"`
Z bool
}
If Outer's embedded Inner3 field was tagged as datastore:"Foo" then the equivalent field would instead be: FooDotZ bool datastore:"Foo.Z".
If an outer struct is tagged "noindex" then all of its implicit flattened fields are effectively "noindex"."
So there shouldn't be any issues with you storing nested structs, just be aware that they will be flattened in datastore. It also mentions the no indexing, saying any field inherits a "noindex" from its parent struct. I don't see why your "noindex" tagging of the inner fields wouldn't work.

Exporting functions with anonymous struct as a parameter [cannot use value (type struct {...}) as type struct {...} in argument to package.Func]

Here is a piece of code play.google.org that runs without any problem:
package main
import (
"fmt"
)
func PrintAnonymous(v struct {
i int
s string
}) {
fmt.Printf("%d: %s\n", v.i, v.s)
}
func PrintAnonymous2(v struct{}) {
fmt.Println("Whatever")
}
func main() {
value := struct {
i int
s string
}{
0, "Hello, world!",
}
PrintAnonymous(value)
PrintAnonymous2(struct{}{})
}
However, if the PrintAnonymous() function exists in another package (let's say, temp), the code will not work:
cannot use value (type struct { i int; s string })
as type struct { i int; s string } in argument to temp.PrintAnonymous
My question are:
Is there a way to call a (public) function with anonymous struct as a parameter (a.k.a. PrintAnonymous() above)?
A function with empty struct as a parameter (a.k.a. PrintAnonymous2() above) can be called even if it exists in another package. Is this a special case?
Well, I know that I can always name the struct to solve the problem, I'm just curious about this, and wonder why it seems that this is not allowed.
The fields of your anonymous struct type are unexported. This means you cannot create values of this struct and specify values for the fields from another package. Spec: Composite literals:
It is an error to specify an element for a non-exported field of a struct belonging to a different package.
If you change the struct definition to export the fields, then it will work because all fields can be assigned to by other packages (see Siu Ching Pong -Asuka Kenji-'s answer).
This is the case with the empty struct (with no fields) too: the empty struct has no fields, thus it has no unexported fields, so you're allowed to pass a value of that.
You can call the function with unmodified struct (with unexported fields) via reflection though. You can obtain the reflect.Type of the PrintAnonymous() function, and you can use Type.In() to get the reflect.Type of its first parameter. That is the anonymous struct we want to pass a value for. And you can construct a value of that type using reflect.New(). This will be a reflect.Value, wrapping a pointer to the zero value of the anonymous struct. Sorry, you can't have a struct value with fields having non-zero values (for reason mentioned above).
This is how it could look like:
v := reflect.ValueOf(somepackage.PrintAnonymous)
paramt := v.Type().In(0)
v.Call([]reflect.Value{reflect.New(paramt).Elem()})
This will print:
0:
0 is zero value for int, and "" empty string for string.
For deeper inside into the type system and structs with unexported fields, see related questions:
Identify non builtin-types using reflect
How to clone a structure with unexported field?
Interestingly (this is a bug, see linked issue below), using reflection, you can use a value of your own anonymous struct type (with matching, unexported fields), and in this case we can use values other than the zero value of the struct fields:
value := struct {
i int
s string
}{
1, "Hello, world!",
}
v.Call([]reflect.Value{reflect.ValueOf(value)})
Above runs (without panic):
1: Hello, world!
The reason why this is allowed is due to a bug in the compiler. See the example code below:
s := struct{ i int }{2}
t := reflect.TypeOf(s)
fmt.Printf("Name: %q, PkgPath: %q\n", t.Name(), t.PkgPath())
fmt.Printf("Name: %q, PkgPath: %q\n", t.Field(0).Name, t.Field(0).PkgPath)
t2 := reflect.TypeOf(subplay.PrintAnonymous).In(0)
fmt.Printf("Name: %q, PkgPath: %q\n", t2.Name(), t2.PkgPath())
fmt.Printf("Name: %q, PkgPath: %q\n", t2.Field(0).Name, t2.Field(0).PkgPath)
Output is:
Name: "", PkgPath: ""
Name: "i", PkgPath: "main"
Name: "", PkgPath: ""
Name: "i", PkgPath: "main"
As you can see the unexported field i in both anonymous struct types (in main package and in somepackage as parameter to PrintAnonymous() function) –falsely– report the same package, and thus their type will be equal:
fmt.Println(t == t2) // Prints true
Note: I consider this a flaw: if this is allowed using reflection, then this should be possible without using reflection too. If without reflection the compile-time error is justified, then using reflection should result in runtime panic. I opened an issue for this, you can follow it here: issue #16616. Fix currently aims Go 1.8.
Oh! I just realized that the field names are in lowercase, and thus not public! Changing the first letter of the field names to uppercase solves the problem:
package main
import (
"temp"
)
func main() {
value := struct {
I int
S string
}{
0, "Hello, world!",
}
temp.PrintAnonymous(value)
temp.PrintAnonymous2(struct{}{})
}
package temp
import (
"fmt"
)
func PrintAnonymous(v struct{I int; S string}) {
fmt.Printf("%d: %s\n", v.I, v.S)
}
func PrintAnonymous2(v struct{}) {
fmt.Println("Whatever")
}

How to set default values in Go structs

There are multiple answers/techniques to the below question:
How to set default values to golang structs?
How to initialize structs in golang
I have a couple of answers but further discussion is required.
One possible idea is to write separate constructor function
//Something is the structure we work with
type Something struct {
Text string
DefaultText string
}
// NewSomething create new instance of Something
func NewSomething(text string) Something {
something := Something{}
something.Text = text
something.DefaultText = "default text"
return something
}
Force a method to get the struct (the constructor way).
From this post:
A good design is to make your type unexported, but provide an exported constructor function like NewMyType() in which you can properly initialize your struct / type. Also return an interface type and not a concrete type, and the interface should contain everything others want to do with your value. And your concrete type must implement that interface of course.
This can be done by simply making the type itself unexported. You can export the function NewSomething and even the fields Text and DefaultText, but just don't export the struct type something.
Another way to customize it for you own module is by using a Config struct to set default values (Option 5 in the link). Not a good way though.
One problem with option 1 in answer from
Victor Zamanian is that if the type isn't exported then users of your package can't declare it as the type for function parameters etc. One way around this would be to export an interface instead of the struct e.g.
package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
Name string
Votes uint32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
return candidate{name, 0} // enforce the default value here
}
Which lets us declare function parameter types using the exported Candidate interface.
The only disadvantage I can see from this solution is that all our methods need to be declared in the interface definition, but you could argue that that is good practice anyway.
There is a way of doing this with tags, which
allows for multiple defaults.
Assume you have the following struct, with 2 default
tags default0 and default1.
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
Now it's possible to Set the defaults.
func main() {
ptr := &A{}
Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...
Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}
Here's the complete program in a playground.
If you're interested in a more complex example, say with
slices and maps, then, take a look at creasty/defaultse
From https://golang.org/doc/effective_go.html#composite_literals:
Sometimes the zero value isn't good enough and an initializing constructor is necessary, as in this example derived from package os.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := new(File)
f.fd = fd
f.name = name
f.dirinfo = nil
f.nepipe = 0
return f
}
What about making something like this:
// Card is the structure we work with
type Card struct {
Html js.Value
DefaultText string `default:"html"` // this only works with strings
}
// Init is the main function that initiate the structure, and return it
func (c Card) Init() Card {
c.Html = Document.Call("createElement", "div")
return c
}
Then call it as:
c := new(Card).Init()
I found this thread very helpful and educational. The other answers already provide good guidance, but I wanted to summarize my takeaways with an easy to reference (i.e. copy-paste) approach:
package main
import (
"fmt"
)
// Define an interface that is exported by your package.
type Foo interface {
GetValue() string // A function that'll return the value initialized with a default.
SetValue(v string) // A function that can update the default value.
}
// Define a struct type that is not exported by your package.
type foo struct {
value string
}
// A factory method to initialize an instance of `foo`,
// the unexported struct, with a default value.
func NewFoo() Foo {
return &foo{
value: "I am the DEFAULT value.",
}
}
// Implementation of the interface's `GetValue`
// for struct `foo`.
func (f *foo) GetValue() string {
return f.value
}
// Implementation of the interface's `SetValue`
// for struct `foo`.
func (f *foo) SetValue(v string) {
f.value = v
}
func main() {
f := NewFoo()
fmt.Printf("value: `%s`\n", f.GetValue())
f.SetValue("I am the UPDATED value.")
fmt.Printf("value: `%s`\n", f.GetValue())
}
One way to do that is:
// declare a type
type A struct {
Filed1 string
Field2 map[string]interface{}
}
So whenever you need a new variable of your custom defined type just call the NewA function also you can parameterise the function to optionally assign the values to the struct fields
func NewA() *A {
return &A{
Filed1: "",
Field2: make(map[string]interface{}),
}
}
for set default values in Go structs we use anonymous struct:
Person := struct {
name string
age int
city string
}{
name: "Peter",
age: 21,
city: "Noida",
}
fmt.Println(Person)
Structs
An easy way to make this program better is to use a struct. A struct is a type which contains named fields. For example we could represent a Circle like this:
type Circle struct {
x float64
y float64
r float64
}
The type keyword introduces a new type. It's followed by the name of the type (Circle), the keyword struct to indicate that we are defining a struct type and a list of fields inside of curly braces. Each field has a name and a type. Like with functions we can collapse fields that have the same type:
type Circle struct {
x, y, r float64
}
Initialization
We can create an instance of our new Circle type in a variety of ways:
var c Circle
Like with other data types, this will create a local Circle variable that is by default set to zero. For a struct zero means each of the fields is set to their corresponding zero value (0 for ints, 0.0 for floats, "" for strings, nil for pointers, …) We can also use the new function:
c := new(Circle)
This allocates memory for all the fields, sets each of them to their zero value and returns a pointer. (*Circle) More often we want to give each of the fields a value. We can do this in two ways. Like this:
c := Circle{x: 0, y: 0, r: 5}
Or we can leave off the field names if we know the order they were defined:
c := Circle{0, 0, 5}
type Config struct {
AWSRegion string `default:"us-west-2"`
}

Resources