How do I pass a pointer to a structure in a function? - go

I wonder how to replace *Type by ? What address has the structure inside?
//mycode.go
package main
import "fmt"
func out(k *Type) {
fmt.Println(k)
}
func main() {
type DataIP struct{ Title, Desc string }
Data := DataIP{
"Hello!",
"Hello GO!",
}
out(&Data)
}

You need to define the type DataIP outside of main() that the type is in the scope of the package and not just inside of the main function:
package main
import "fmt"
type DataIP struct{ Title, Desc string }
func out(k *DataIP) {
fmt.Println(k)
}
func main() {
Data := DataIP{
"Hello!",
"Hello GO!",
}
out(&Data)
}
https://play.golang.org/p/cUS6ttcUy-

I am not sure to understand your question.
If you want out to work only with structs of type DataIP:
simply define DataIP outside of main and use the signature func out(k *DataIP).
if what you want is to be able to pass any type of structure to out:
In golang, this sort of generic methods can be implemented using the interface type. As this answer explains, an interface is a container with two words of data:
one word is used to point to a method table for the value’s underlying type,
and the other word is used to point to the actual data being held by that value.
An interface can hold anything and is often used as a function parameter to be able to process many sort of inputs.
In your case, you can do:
func out(k interface{}) {
fmt.Println(k)
}
This will print &{Hello! Hello GO!}. In case you want the & to disappear (i.e. you always pass it pointers), you can use the reflect package to "dereference" k:
func out(k interface{}) {
fmt.Println(reflect.ValueOf(k).Elem())
}
which yields {Hello! Hello GO!}
Here is a playground example.
if what you want is to print the address of Data:
you can use the %p pattern with fmt.Printf:
fmt.Printf("%p", &Data) // 0x1040a130
Using the out function, you get:
func out(k interface{}) {
fmt.Printf("%p\n", k)
}
See this playground example

Related

Dynamic Type Assertion Golang

I'm trying to convert an interface dynamically back to it's original struct but I am having issues accessing attributes of the struct after the conversion.
Take this code for example.
package main
import (
"fmt"
"log"
)
type struct1 struct {
A string
B string
}
type struct2 struct {
A string
C string
}
type struct3 struct {
A string
D string
}
func main() {
s1 := struct1{}
s1.A = "A"
structTest(s1)
s2 := struct2{}
s2.A = "A"
structTest(s2)
s3 := struct3{}
s3.A = "A"
structTest(s3)
}
func structTest(val interface{}) {
var typedVal interface{}
switch v := val.(type) {
case struct1:
fmt.Println("val is struct1")
case struct2:
fmt.Println("val is struct2")
case struct3:
fmt.Println("val is struct3")
default:
log.Panic("not sure what val is.")
}
fmt.Println(typedVal.A)
}
I would like to be able to pass in one of 3 known struct types into my function. Then figure out which struct type was passed in to type assert it. Finally I want to be able to access like attributes.
Basically I want to have some basic inheritance in my structs, but so far it seems that it is not possible to do this in go. I saw some posts mentioning inheritance using an interface, but my structs have no methods so I'm not sure how I would use an interface.
Is something like this possible in go?
I would like to be able to pass in one of 3 known struct types into my function. Then figure out which struct type was passed in to type assert it. Finally I want to be able to access like attributes.
You can use type assertions to do exactly that. Basic idea is, in any case of the type switch just use type assertion to get a concrete instance of the corresponding type and then you can call whatever properties that you wish.
Take a look at the following example
package main
import (
"fmt"
)
type test1 struct {
A, B string
}
type test2 struct {
A, C string
}
func testType(val interface{}) {
switch val.(type) {
case test1:
t := val.(test1)
fmt.Println(t.B)
break
case test2:
t := val.(test2)
fmt.Println(t.C)
break
}
}
func main() {
t1, t2 := test1{B: "hello"}, test2{C: "world"}
testType(t1)
testType(t2)
}
Playground
Function structTest(val interface{}) in your code seems to be loosely typed. You pass it an untyped argument and expect it will satisfy some condition (will have field A), it looks strange in any typed language.
Using an interface this kind of polymorphism, in Go, to my mind, can be expressed something like
package main
import (
"fmt"
"log"
)
type A string
type HasA interface {
PrintA()
}
func (a A) PrintA() { fmt.Println(a) }
type struct1 struct {
A
B string
}
type struct2 struct {
A
C string
}
type struct3 struct {
A
D string
}
func main() {
s1 := struct1{}
s1.A = "A"
structTest(s1)
s2 := struct2{}
s2.A = "A"
structTest(s2)
s3 := struct3{}
s3.A = "A"
structTest(s3)
}
func structTest(val HasA) {
switch val.(type) {
case struct1:
fmt.Println("val is struct1")
case struct2:
fmt.Println("val is struct2")
case struct3:
fmt.Println("val is struct3")
default:
log.Panic("not sure what val is.")
}
val.PrintA()
}
Playground

Golang interface to struct

I have a function that has a parameter with the type interface{}, something like:
func LoadTemplate(templateData interface{}) {
In my case, templateData is a struct, but each time it has a different structure. I used the type "interface{}" because it allows me to send all kind of data.
I'm using this templateData to send the data to the template:
err := tmpl.ExecuteTemplate(w, baseTemplateName, templateData)
But now I want to append some new data and I don't know how to do it because the "interface" type doesn't allow me to add/append anything.
I tried to convert the interface to a struct, but I don't know how to append data to a struct with an unknown structure.
If I use the following function I can see the interface's data:
templateData = appendAssetsToTemplateData(templateData)
func appendAssetsToTemplateData(t interface{}) interface{} {
switch reflect.TypeOf(t).Kind() {
case reflect.Struct:
fmt.Println("struct")
s := reflect.ValueOf(t)
fmt.Println(s)
//create a new struct based on current interface data
}
return t
}
Any idea how can I append a child to the initial interface parameter (templateData)? Or how can I transform it to a struct or something else in order to append the new child/data?
Adrian is correct. To take it a step further, you can only do anything with interfaces if you know the type that implements that interface. The empty interface, interface{} isn't really an "anything" value like is commonly misunderstood; it is just an interface that is immediately satisfied by all types.
Therefore, you can only get values from it or create a new "interface" with added values by knowing the type satisfying the empty interface before and after the addition.
The closest you can come to doing what you want, given the static typing, is by embedding the before type in the after type, so that everything can still be accessed at the root of the after type. The following illustrates this.
https://play.golang.org/p/JdF7Uevlqp
package main
import (
"fmt"
)
type Before struct {
m map[string]string
}
type After struct {
Before
s []string
}
func contrivedAfter(b interface{}) interface{} {
return After{b.(Before), []string{"new value"}}
}
func main() {
b := Before{map[string]string{"some": "value"}}
a := contrivedAfter(b).(After)
fmt.Println(a.m)
fmt.Println(a.s)
}
Additionally, since the data you are passing to the template does not require you to specify the type, you could use an anonymous struct to accomplish something very similar.
https://play.golang.org/p/3KUfHULR84
package main
import (
"fmt"
)
type Before struct {
m map[string]string
}
func contrivedAfter(b interface{}) interface{} {
return struct{
Before
s []string
}{b.(Before), []string{"new value"}}
}
func main() {
b := Before{map[string]string{"some": "value"}}
a := contrivedAfter(b)
fmt.Println(a)
}
You can't append data arbitrarily to a struct; they're statically typed. You can only assign values to the fields defined for that specific struct type. Your best bet is probably to use a map instead of structs for this.
Not recommended, but you can create structs dynamically using the reflect package.
Here is an example:
package main
import (
"encoding/json"
"os"
"reflect"
)
type S struct {
Name string
}
type D struct {
Pants bool
}
func main() {
a := Combine(&S{"Bob"}, &D{true})
json.NewEncoder(os.Stderr).Encode(a)
}
func Combine(v ...interface{}) interface{} {
f := make([]reflect.StructField, len(v))
for i, u := range v {
f[i].Type = reflect.TypeOf(u)
f[i].Anonymous = true
}
r := reflect.New(reflect.StructOf(f)).Elem()
for i, u := range v {
r.Field(i).Set(reflect.ValueOf(u))
}
return r.Addr().Interface()
}
You could use something like the Combine function above to shmush any number of structs together. Unfortunately, from the documentation:
StructOf currently does not generate wrapper methods for embedded fields. This limitation may be lifted in a future version.
So your created struct won't inherit methods from the embedded types. Still, maybe it does what you need.
If you are just looking to convert your interface to struct, use this method.
type Customer struct {
Name string `json:"name"`
}
func main() {
// create a customer, add it to DTO object and marshal it
receivedData := somefunc() //returns interface
//Attempt to unmarshall our customer
receivedCustomer := getCustomerFromDTO(receivedData)
fmt.Println(receivedCustomer)
}
func getCustomerFromDTO(data interface{}) Customer {
m := data.(map[string]interface{})
customer := Customer{}
if name, ok := m["name"].(string); ok {
customer.Name = name
}
return customer
}

Implications of defining a struct inside a function vs outside?

Are there any implications (GC churn, performance, or otherwise) to defining a 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 situation where one is preferred over the other?
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.
A struct defined starting with an upper case letter will be exportable, meaning it can be accessed from other packages.
A struct defined starting with a lower case letter can be accessed from anything within the same package but not externally.
A struct defined in a function inline can only be accessed/initialized by that function.
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.
For Konrad Kleine's problem, you can still do it with some workaround like this
https://play.golang.org/p/50yv66LUNRt
package main
import (
"fmt"
)
func main() {
type MyType struct {
Name string
String func() string
}
InitMyType := func(m *MyType) {
m.String = func() string {
return m.Name
}
return
}
m := MyType{Name: "Hello, World!"}
initMyType(&m)
fmt.Println(m.String())
}
I agree the difference is just accessibility.
But this is still very useful, especially what you want is only a temp struct, or when you do unit test, there are many similar struct like args, test case in a package, you won't need bother to name them one by one.

Passing in a type variable into function

I'm trying to achieve a type assertion by passing in a type into a function. In other words, I'm trying to achieve something like this:
// Note that this is pseudocode, because Type isn't the valid thing to use here
func myfunction(mystring string, mytype Type) {
...
someInterface := translate(mystring)
object, ok := someInterface.(mytype)
... // Do other stuff
}
func main() {
// What I want the function to be like
myfunction("hello world", map[string]string)
}
What's the proper function declaration I need to use in myfunction, to successfully perform the type assertion in myfunction?
#hlin117,
Hey, if I understood your question correctly and you need to compare the types, here's what you can do:
package main
import (
"fmt"
"reflect"
)
func myfunction(v interface{}, mytype interface{}) bool {
return reflect.TypeOf(v) == reflect.TypeOf(mytype)
}
func main() {
assertNoMatch := myfunction("hello world", map[string]string{})
fmt.Printf("%+v\n", assertNoMatch)
assertMatch := myfunction("hello world", "stringSample")
fmt.Printf("%+v\n", assertMatch)
}
The approach is to use a sample of the type you'd like to match.

How to use passed struct in function

I saw somewhere, but I do not remember where, that a slice struct is passing through function like the following code snippet.
package main
import "fmt"
func passSlice(arg interface{}) {
fmt.Println(arg)
}
func main() {
res := []struct {
Name string
}{}
passSlice(res)
}
I have no idea, how to use here a slice struct in the function. Have someone a idea, how can I use it in the function?
In order to use the slice struct (or any other value stored in an interface), you must first do a type assertion or type switch:
Type assertion:
func passSlice(arg interface{}) {
// Put args value in v if it is of type []struct{ Name string }
v, ok := arg.([]struct{ Name string })
if !ok {
// did not contain a value of type []struct{Name string}
return
}
for _, s := range v {
fmt.Println(s.Name)
}
}
Playground: http://play.golang.org/p/KiFeVC3VQ_
Type switches are similar, but can have cases for multiple types.
There is also an option of using the reflect package, allowing you to more dynamically handle interface values without knowing before hand what types you can expect, but using reflection is also more complex. To know more about using reflection in Golang, you can look here:
Laws of reflection
reflect package

Resources