I have following code
package main
import (
"fmt"
)
var dog struct {
Name string
Age int
Breed string
}
func main() {
dog.Name = "Pongo"
dog.Age = 7
dog.Breed = "Dalmatian"
fmt.Println(dog)
// Reset struct.
dog{} --- Problem point with error
fmt.Println(dog)
dog.Name = "Fluffy"
dog.Breed = "Poodle"
fmt.Println(dog)
}
I am trying to clear out the global struct in Reset.
I know I can do it individually. I am looking into golang way of doing like we can do it for struct as follow
type Dog struct {
Name string
Age int
Breed string
}
dog = Dog {}
If you have a variable of struct type, you may zero it by assigning the zero value of its type.
As noted by others, since you have a variable of anonymous type, the composite literal has to repeat the struct definition:
// Reset with struct literal:
dog = struct {
Name string
Age int
Breed string
}{}
This is inconvenient. So just use a named type.
You could also do it with reflection:
// Reset using reflection:
p := &dog
v := reflect.ValueOf(p).Elem()
v.Set(reflect.New(v.Type()).Elem())
The advantage here is that we didn't have to repeat the struct definition, and this solution works with all structs (and other types too). But using reflection is slower. Again, just use a named type.
You may try the examples on the Go Playground.
What's wrong with the solution you proposed? That is how you would do it:
package main
import (
"fmt"
)
type Dog struct {
Name string
Age int
Breed string
}
var dog = Dog{}
func main() {
dog.Name = "Pongo"
dog.Age = 7
dog.Breed = "Dalmatian"
fmt.Println(dog)
// Reset struct.
dog = Dog{}
fmt.Println(dog)
dog.Name = "Fluffy"
dog.Breed = "Poodle"
fmt.Println(dog)
}
Related
If I have a two different structs, that mostly overlap each other in regards to their property types, and I need to create one from the other, is there some more concise way to do so w/o having to verbosely set each and every property?
Example: https://go.dev/play/p/k4TUrWQ7JLD
package main
import (
"fmt"
)
type Foo struct {
A int64
B string
C []string
D []int
// many other properties
}
type Bar struct {
A string
B string
C []int64
D []int
// many other properties
}
func getBarA(a int64) string {
// somhow map an int64 from Foo to a string for Bar
return "A"
}
func getBarC(a []string) []int64 {
// somhow map an int64 from Foo to a string for Bar
return []int64{1, 2, 3}
}
func getABarFromFoo(foo Foo) Bar {
return Bar{
A: getBarA(foo.A),
B: foo.B,
C: getBarC(foo.C),
D: foo.D,
// All the rest of possibly MANY properties :-(
}
}
func main() {
b := getABarFromFoo(Foo{})
fmt.Println(b)
}
As you can imagine, this mapping can get very repetitive/verbose… is there some way to just do something simple like this? (yes, I know this isn’t proper Go)
b:= Bar{
...foo,
A: getBarA(foo.A),
B: getBarC(foo.C),
}
I'm looking/hoping/🙏 for is a way to essentially say:
"Give me a Bar, created entirely from the compatible properties of a given Foo instance.
And for [these] few incompatible properties, here's how to set those."
Well.
b:= Bar{
...foo,
A: getBarA(foo.A),
B: getBarC(foo.C),
}
You can't assign []int64 returned from getBarC to string B. You might want to assign it to C instead.
I think you can't copy like javascript using spread operator. Even if you could, this will cause build error "duplicate field name ". What you can do is to keep a field Foo inside Bar and then convert the instance of Foo, namely foo, to bar which is an instance of Bar.
package main
import (
"fmt"
)
type Foo struct {
A int64
B string
C []string
D []int
// many other properties
}
type Bar struct {
Foo
A string
B string
C []int64
D []int
// many other properties
}
func getBarA(a int64) string {
// somhow map an int64 from Foo to a string for Bar
return "A"
}
func getBarC(a []string) []int64 {
return []int64{1, 2, 3}
}
func getABarFromFoo(foo Foo) Bar {
bar := Bar{Foo: foo}
bar.A = getBarA(foo.A)
bar.C = getBarC(foo.C)
return bar
}
func main() {
b := getABarFromFoo(Foo{})
fmt.Println(b) // just don't sweat over empty Foo inside b
}
If some fields of two different structures overlap somehow, the answer is Object Orientation.
You should think about the relationship between Foo and Bar.
For instance there may share a embed common substructure. But why?
You should only copy and convert parameters. You can serialize/deserialize it to convert from/to any type with given rules.
Perhaps Foo knowns how to convert to Bar. Or Bar have a constructor who accepts Foo. Or Base.
type Base struct{
B string
D [] int
}
type Foo struct {
Base
A string
C []int
}
How can I pass a dynamic array struct as parameter in golang
For e.g
type Dog {
Name string
}
type Cat {
Name uint
}
I want a function which takes array of either cat or dog as an argument and loop through the array in the function . Below is function of what I wanna achive
func (array of either cats or dogs ){
for _ , item := range (array of either cats or dogs) {
}
}
I am assuming you mean
type Dog struct{
Name string
}
type Cat struct{
Name uint
}
Your function should accept interface{} as an argument, so you are free to send either Dog or Cat or whatever you want as an argument. But after accepting the data you need to apply Type assertion inside the function to extract the specific data type in order to loop over it as you can't loop over the interface.
x := args.(type) // x will contain the name of the data type store inside the interface{}
Or you could use
x := i.(Dog) //if you're absolutely sure that the data type is Dog
x, ok := i.(Cat) //If you're not sure and want to avoid runtime panic
Please read the Go Tour examples to learn more about type assertions.
Edit:
In the comments #mkopriva suggested func F(slice ...interface{}), so you need to convert the slice of Dog or Cat to slice of interface{} for that function signature to work. You will have manually to add/append each element in the Cat or Dog slice to an interface{} slice to convert from slice of Cat or Dog to slice of interface{} slice.
interface{} is one way to go, as mentioned in Answers.
I find the other interfaces also useful:
import (
"fmt"
)
type Pet interface{}
type Dog struct {
Pet
Name string
}
type Cat struct {
Pet
Name uint
}
func listPets(pets []Pet) {
for _, pet := range pets {
fmt.Println(pet)
}
}
func main() {
pets := []Pet{Dog{Name: "Rex"}, Dog{Name: "Boss"}, Cat{Name: 394}}
listPets(pets)
}
https://play.golang.org/p/uSiYmcrSuqJ
Like code here, when embedding an interface A into struct B, and then set A to aa which is an instance of AA. Both B and AA have element X, when call b.X I just got B.X. How can I get b.AA.X? I know this syntax is wired, but I just want to figure out how var b is stored in the memory, I tried some unsafe syntax, no way to get b.A.X.:
package main
import (
"fmt"
"unsafe"
)
type A interface {
Hello() string
}
type B struct {
A
X string
}
type AA struct {
num int
X string
}
func (aa AA) Hello() string {
return fmt.Sprintf("hello %d from %s", aa.num, aa.X)
}
func main() {
aa := AA{200, "golang"}
b := B{A: aa, X: "python"}
fmt.Println(b.X) // output: python
fmt.Printf("--->%d\n", ((*AA)(unsafe.Pointer(&b.A)).num)) // output: --->17667104
fmt.Printf("===>%+v\n", b.A) // output: ===>{num:200 X:golang}
}
Embedded fields are accessed by their type name, and fields of an interface are only accessible by asserting the underlying type, so b.A.(AA).X will get you field X of the underlying AA that's in b.A. But if you're needing to access fields, you probably shouldn't be embedding the interface type anyway, you should be embedding the concrete type.
I defined a struct in C like:
struct SomeStruct
{
int var1;
bool var2;
double var3;
int var4[10];
int var5[10][10];
}
struct SomeStruct entity;
And somewhere there was a input box that some user input in GO:
func("entity.var3")
It will return value of entity.var3 in C struct.
Actually I could already implement it in python by cffi and:
def get_one_variable(buffer, setup):
value = buffer
for level in setup:
if isinstance(level, str):
value = getattr(value, level)
else:
[base, extends] = level
value = getattr(value, base)
for extend in extends:
value = value[extend]
return value
Where buffer is python cffi data pointer defined with "FFI.cdef" and setup resolved by:
def parse_variable(self, line):
line = line.replace('\n', '').replace(' ', '')
split = line.split('.')
variable = []
for child in split:
match = self.BASE_EXT_REGEX.match(child)
if match is None:
variable.append(child)
else:
base_name = match.group('base_name')
ext_name = match.group('ext_name')
variable.append([base_name, [int(index) for index in
ext_name.replace('[', ']').replace(']]', ']').strip(']').split(']')]])
return variable
So I can dynamically resolve "entity.var1", "entity.var2", "entity.var3", "entity.var4[0]", "entity.var5[0][1]".
Is there something or someway similar in GO?
This is handled by CGO which is a special package in Go that allows for easy C integration. You can read more about it here and here. Given your examples, a simple CGO example would be:
/*
struct SomeStruct
{
int var1;
bool var2;
double var3;
int var4[10];
int var5[10][10];
}
*/
import "C"
import "fmt"
func main(){
thing := C.struct_SomeStruct{}
thing.var1 = C.int(5)
fmt.Printf("My Struct's var field %d\n",int(thing.var1))
}
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"`
}