Are there any implications (GC churn, performance, or otherwise) to defining an struct
inside a function vs. having it defined outside? For example:
type Outside struct {
Foo string `json:"foo"`
}
func SomeFunc(b []byte) error {
outside := Outside{}
if err := json.NewDecoder(b).Decode(&outside); err != nil {
return err
}
...
}
vs.
func SomeFunc(b []byte) error {
type inside struct {
Foo string `json:"foo"`
}
if err := json.NewDecoder(b).Decode(&inside); err != nil {
return err
}
...
}
Would there be any situations where one is preferred over the other?
Yes, the standard allows this, and yes, the name you create this way is only visible inside the function (i.e., it has local scope, just like when you define int i; , i has local scope). or, if you're really only going to use it once, struct { /* ...
Yes you can. In c++, class and struct are kind of similar. We can define not only structure inside a class, but also a class inside one. It is called inner class.
Note that, if we define the structure inside the main function, then it can not be passed to the functions; i.e. Lines 7-12 of Listing 6.6 can not be defined inside the main function, as it will generate error.
1 Answer. No, you cannot define a function inside the structure of C Programming, but you can do so in C++, rather you can have a function pointer in a “struct” in C Language.
To me the main drawback for a type defined in a function is that you cannot define methods on that type.
See this example https://play.golang.org/p/cgH01cRwDv6:
package main import ( "fmt" ) func main() { type MyType struct { Name string } // You cannot define a method on your type // defined in a function, can you? func (m MyType) String() string { return m.Name } m := MyType{Name: "Hello, World!"} fmt.Println(m) }
The above example will fail with the error prog.go:15:27: expected ';', found 'IDENT' string (and 1 more errors)
.
There is no performance difference – it's only a difference of scope (i.e., where the type definition can be seen). If you only need the type within a single function, it's fine to define it there.
As others have noted, if you define a type at the package level (i.e., outside of a function) with a name beginning with a capital letter, it will be exported (i.e., visible outside the package). If the name doesn't begin with a capital letter, it will only be visible within the package.
My understanding is the difference is just in accessibility.
For me I once defined a struct inside a function for marshalling JSON byte array ([]byte)
into the struct instance, and extract a message from the instance.
Obviously it is not required to define the struct. I could have extracted the message by marshalling the JSON byte array into interface{}
and then cast recursively to get the required message.
By defining the struct, extraction of the message becomes very easy :)
var errDetail struct {
Message string `json:"message"`
Success bool `json:"success"`
}
json.Unmarshal(*bytes, &errDetail)
if errDetail.Message == "" {
fmt.Println("error message is not present")
return nil
}
return errDetail.Message
As others have mentioned its all about limit the variables scope. If you are going to use a struct inside a function, you could also use an anonymous struct.
package main
import (
"fmt"
)
func main() {
m := struct {
greeting string
name string
}{
greeting: "hello",
name: "world",
}
fmt.Printf("%v %v\n", m.greeting, m.name)
}
If you're only planing to use the struct inside the function you can define the fields of the struct and assign values to them right away.
The scope is different, you can check in Golang spec here:
Most related parts are:
Go is lexically scoped using blocks:
The scope of an identifier denoting a constant, type, variable, or function (but not method) declared at top level (outside any function) is the package block.
The scope of a type identifier declared inside a function begins at the identifier in the TypeSpec and ends at the end of the innermost containing block.
And if you use go tool compile -S -N hello.go
to check the generated assembly code, you can spot the names of type defined in package level and names of type defined inside function are different.
Package level
package main
import (
"fmt"
)
type Point struct {
X, Y int
}
func main() {
fmt.Printf("%v\n", Point{X: 1, Y: 2})
}
Then try to compile and find this line: type."".Point SRODATA size=144
.
Inside function
package main
import (
"fmt"
)
func main() {
type Point struct {
X, Y int
}
fmt.Printf("%v\n", Point{X: 1, Y: 2})
}
Then try to find this line: type.*"".Point·1 SRODATA size=56
Than means, they just got different names after compiled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With