How to pass interface pointer through a function in Golang? - go

I was testing golang functionalities and came across this concept where I can use a pointer of an interface as an interface itself. In the below code, how do I ensure that the value of one changes to random.
package main
import (
"fmt"
)
func some(check interface{}) {
check = "random"
}
func main() {
var one *interface{}
some(one)
fmt.Println(one)
}
Specifically, I need ways in which I can pass an interface pointer to a function which accepts an interface as an argument.
Thanks!

Accept a pointer to interface{} as the first parameter to some
Pass the address of one to some
package main
import (
"fmt"
)
func some(check *interface{}) {
*check = "random"
}
func main() {
var one interface{}
some(&one)
fmt.Println(one)
}
https://play.golang.org/p/ksz6d4p2f0
If you want to keep the same signature of some, you will have to use the reflect package to set the interface{} pointer value:
package main
import (
"fmt"
"reflect"
)
func some(check interface{}) {
val := reflect.ValueOf(check)
if val.Kind() != reflect.Ptr {
panic("some: check must be a pointer")
}
val.Elem().Set(reflect.ValueOf("random"))
}
func main() {
var one interface{}
some(&one)
fmt.Println(one)
}
https://play.golang.org/p/ocqkeLdFLu
Note: val.Elem().Set() will panic if the value passed is not assignable to check's pointed-to type.

Related

Trying to unmarshal data into interface in golang

Trying to unmarshal data into interface. It is working fine. But If i access res.page or res.Page not working
I got the below error:
res.Page undefined (type interface {} is interface with no methods)
Below is my code:
package main
import (
"encoding/json"
"fmt"
)
func main() {
var res interface{}
str := `{"page": 1, "fruits": ["apple", "peach"]}`
json.Unmarshal([]byte(str), &res)
fmt.Println(res.Page)
}
Thanks in advance.
interface{} specifies zero methods (and ofc zero fields).
What you need is a map[string]interface{}
Try this https://play.golang.org/p/WBwXKob4zdA
package main
import (
"encoding/json"
"fmt"
)
func main() {
var res map[string]interface{}
str := `{"page": 1, "fruits": ["apple", "peach"]}`
json.Unmarshal([]byte(str), &res)
fmt.Println(res["page"])
}
You may want to check:
https://tour.golang.org/methods/14
https://tour.golang.org/methods/15

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

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

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.

unexported struct best practice? (golint complains)

I have the following package :
package mypkg
type (
// mystruct ...
mystruct struct {
S string
}
)
// New ..
func New() *mystruct {
return &mystruct{S: "test"}
}
I use it this way:
package main
import (
"fmt"
"test/mypkg"
)
func main() {
x := mypkg.New()
fmt.Println(x.S)
// this fails intended
y := mypkg.mystruct{S: "andre"}
fmt.Println(y.S)
}
Why is golint complaining about my unexported struct? My intension is to prevent calling the struct creation outside the constructor call.
Is there another way to prevent instantiating without the New call?
You x := mypkg.New() in main.main() even can't have any type. It should not even compile. It's unusable. Seems to me more meaningful would be something like
package mypkg
type (
// mystruct ...
mystruct struct {
S string
}
)
type HaveS interface{ //which you can use but can't instantiate
GetS() string
}
func (strct *mystruct ) GetS() string {return strct.S}
// New ..
func New() HaveS {
return &mystruct{S: "test"}
}
then in main
var x mypkg.HaveS
x = mypkg.New()
fmt.Println(x.GetS())

How I can get return value based on argument type?

When I define function
func test(a int, b int) int {
//bla
}
I must set arguments and return value types. How I can return value based on argument type, ex
func test(argument type) type {
//if argument type == string, must return string
//or else if argument int, must return integer
}
Can I do this and how?
Go lacks generics, (not going to argue this point one way or the other), you can achieve this by passing interface{} to functions and then doing a type assertion on the other side.
package main
import "fmt"
func test(t interface{}) interface{} {
switch t.(type) {
case string:
return "test"
case int:
return 54
}
return ""
}
func main() {
fmt.Printf("%#v\n", test(55))
fmt.Printf("%#v", test("test"))
}
You will have to type assert the value you get out
v := test(55).(int)
Go does not yet have generics like C# or Java.
It does have an empty interface (interface{})
Here is code that I believe answers your question, if I understood it correctly:
package main
import (
"fmt"
"reflect"
)
type generic interface{} // you don't have to call the type generic, you can call it X
func main() {
n := test(10) // I happen to pass an int
fmt.Println(n)
}
func test(arg generic) generic {
// do something with arg
result := arg.(int) * 2
// check that the result is the same data type as arg
if reflect.TypeOf(arg) != reflect.TypeOf(result) {
panic("type mismatch")
}
return result;
}

Resources