File1.go
Package abc
type ECA struct {
*CA
obcKey []byte
obcPriv, obcPub []byte
gRPCServer *grpc.Server
}
type ECAP struct {
eca *ECA
}
func (ecap *ECAP) ReadCACertificate(ctx context.Context, in *pb.Empty) (*pb.Cert, error) {
Trace.Println("gRPC ECAP:ReadCACertificate")
return &pb.Cert{Cert: ecap.eca.raw}, nil
}
File2.go
package main
import "abc"
var ecap abc.ECAP //creating instance
func main() {
err = ecap.ReadCACertificate(floo,floo)
}
I am a newbie. I want to create instance of ECAP struct and call ReadCACertificate method. Right now i am creating like this "var ecap abc.ECAP //creating instance" which is giving "nil" and nil pointer error.
Can anyone help how to call the ReadCACertificate method in efficient way.
Thanks in advance.
Your example is incomplete, but basically you need to initialize your struct, since it has pointers, and default pointer value is nil.
var ecap := ECAP{new(ECA)}
You need to import the second file from your $GOPATH. And your function return 2 values, not just an error.
package main
import (
"$RELATIVE_PATH_FROM_GOPATH/abc"
)
var ecap := ECAP{new(ECA)} //initialize your struct, since it has pointers
func main() {
cert, err = ecap.ReadCACertificate(floo,floo)
}
File 1
type ECAP struct {
Eca *ECA //uppercase make field be exported
}
Related
Had a rough time trying to set the interface value by using "reflect" package. The interface value is actually inside a struct of a struct. See my code in Go Playground
Basically, inside initProc, I want to assign dummyAFunc function to DummyA field in Box struct
package main
import (
"fmt"
"reflect"
)
type Box struct {
Name string
DummyA interface{}
}
type SmartBox struct {
Box
}
func dummyAFunc(i int) {
fmt.Println("dummyAFunc() is here!")
}
func initProc(inout interface{}) {
// Using "inout interface{}", I can take any struct that contains Box struct
// And my goal is assign dummyAFunc to dummyA in Box struct
iType:=reflect.TypeOf(inout)
iValue:=reflect.ValueOf(inout)
fmt.Println("Type & value:", iType.Elem(), iValue.Elem()) // Type & value: *main.SmartBox &{{ <nil>}}
e := reflect.ValueOf(inout).Elem()
fmt.Println("Can set?", e.CanSet()). // true
fmt.Println("NumField", e.NumField()) // panic: reflect: call of reflect.Value.NumField on ptr Value ?????
fmt.Println("NumMethod", e.NumMethod()) // NumMethod = 0
}
func main() {
smartbox := new (SmartBox)
initProc(&smartbox)
}
I'm new to Go and I've read the The laws of Reflection but still can't figure it out. Please help. Thanks!
You are passing a **SmartBix to initProc. So when you dereference once with reflect's Elem() you are still getting a pointer (*Smart box).
Since new already returns a pointer, just use:
smartbox := new (SmartBox)
// InitProc(smartbox) // **SmartBox
InitProc(smartbox) // *SmartBox
https://play.golang.org/p/j4q6aq6QL_4
EDIT
To update the input struct's DummyA field, you can do something like this:
func initProc2(v interface{}) error {
if reflect.TypeOf(v).Kind() != reflect.Ptr {
return fmt.Errorf("value must be a pointer")
}
dv := reflect.ValueOf(v).Elem()
if dv.Kind() != reflect.Struct {
return fmt.Errorf("value must be a pointer to a struct/interface")
}
const fname = "DummyA" // lookup field name
f := dv.FieldByName(fname)
if !f.CanSet() {
return fmt.Errorf("value has no field %q or cannot be set", fname)
}
nv := reflect.ValueOf(dummyAFunc)
f.Set(nv)
return nil
}
Working example: https://play.golang.org/p/VE751GtSGEw
I am working with reflection in Go and have some issues trying to call a method on a struct that has a pointer receiver. I have the following go code:
package main
import (
"fmt"
"reflect"
)
type Base struct {
Name string
Greeting string
}
func (b *Base) SetGreeting() {
b.Greeting = fmt.Sprintf("Hello %s\n", b.Name)
}
func main() {
var pointer interface{}
// create a new instance of base
mybase := Base{
Name: "reflect",
}
// create a pointer to the base
pointer = &mybase
s := reflect.ValueOf(pointer).Elem()
// get the value of s which should be a pointer
vv := reflect.ValueOf(s)
switch vv.Kind() {
case reflect.Struct:
fmt.Println("struct")
case reflect.Ptr:
fmt.Println("pointer")
}
// output struct property
fmt.Println(s.FieldByName("Name").String())
// call the method using reflect
sayHelloFunc := s.MethodByName("SetGreeting")
if sayHelloFunc.IsValid() {
sayHelloFunc.Call([]reflect.Value{})
} else {
fmt.Println("Unable to find method")
}
fmt.Println(s.FieldByName("Greeting").String())
}
The above is available at https://play.golang.org/p/V04m3LJlRia
If I change the method to use a value receiver then the method works, but I am not able to get the Greeting property. If use the pointer receiver (as in the code) the method cannot be found but I can access the property.
How can I do both?
Thanks to #Volker this is now working. The slightly modified code is:
package main
import (
"fmt"
"reflect"
)
type Base struct {
Name string
Greeting string
}
func (b *Base) SetGreeting() {
b.Greeting = fmt.Sprintf("Hello %s\n", b.Name)
}
func main() {
var pointer interface{}
// create a new instance of base
mybase := Base{
Name: "reflect",
}
// create a pointer to the base
pointer = &mybase
s := reflect.ValueOf(pointer)
// get the value of s which should be a pointer
vv := reflect.ValueOf(s)
switch vv.Kind() {
case reflect.Struct:
fmt.Println("struct")
case reflect.Ptr:
fmt.Println("pointer")
}
// output struct property
fmt.Println(s.Elem().FieldByName("Name").String())
// call the method using reflect
sayHelloFunc := s.MethodByName("SetGreeting")
if sayHelloFunc.IsValid() {
sayHelloFunc.Call([]reflect.Value{})
} else {
fmt.Println("Unable to find method")
}
fmt.Println(s.Elem().FieldByName("Greeting").String())
}
As can be seen s is no longer set as a pointer and the method can be called.
As I wanted to be able to call the properties on s I then make it a pointer using .Elem() and then I can use FieldByName.
Updated here https://play.golang.org/p/iiUrB961tUa
This question already has an answer here:
Set reference in Go
(1 answer)
Closed 3 years ago.
Given:
type Savable interface {}
type Customer struct {} // satisfies 'Savable'
func GetSaved(id string, s Savable) {
// somehow get a reference to the object from cache
s = cachedObject
// alternately, something like:
// json.Unmarshal(jsonFromDisk, &s)
}
func Foo() {
c := Customer{}
GetSaved("bob", &c)
}
Trying a few configurations, I either get compilation errors related to "Expects *Savable, found *Customer", or the GetSaved function doesn't actually change what I want to be the 'output variable'. Is this doable, and I'm just not getting the right mix of interface/pointers/etc? Or is this not possible for some reason?
Edit: A working example illustrating the problem.
You can use reflection to set the passed interface.
Even when a struct reference is passed as interface, the underlying type info is not lost and we can use reflection.
package main
import (
"fmt"
"reflect"
)
type Savable interface {}
type Customer struct {
Name string
}
func GetSaved(id string, s Savable) {
cached := Customer{ Name: id }
c1 := reflect.ValueOf(cached)
reflect.ValueOf(s).Elem().Set(c1)
}
func main() {
c := Customer{}
fmt.Printf("Before: %v\n", c)
GetSaved("bob", &c)
fmt.Printf("After: %v\n", c)
}
Here is the running link
This works I converted it to bytes and Unmarshaled it back into your structure. Hope this helps. :)
package main
import (
"encoding/json"
"fmt"
)
type Savable interface{}
type Customer struct {
Name string
} // satisfies 'Savable'
func GetSaved(id string, s Savable) {
// somehow get a reference to the object from cache
cached := Customer{Name: "Bob"}
byt, _ := json.Marshal(cached)
_ = json.Unmarshal(byt, &s)
}
func main() {
c := Customer{}
GetSaved("bob", &c)
fmt.Println(c)
}
Run link: https://play.golang.org/p/NrBRcRmXRVZ
Please ignore that this seems like a bad idea, is bad style, etc.
The main issue here is that process() gets a pointer to a struct of an unknown type passed in as interface{} and I need to clone the underlying struct.
The core issue is that I can't figure out how to deference the pointer, since its passed in as interface{}, so I can clone the underlying struct and return it.
package main
import (
"fmt"
"reflect"
)
type Foo struct {
Value string
}
func main() {
foo1 := Foo{"bar"}
foo2 := process(&foo1)
result := reflect.DeepEqual(foo1, foo2)
fmt.Println(result) // how do I make this true?
}
// objective: pointer to struct is passed it, clone of underlying struct is returned
func process(i interface{}) interface{} {
return clone(i)
}
Using some reflection magic, I was able to get this to work. Thanks, JimB, for all your help! The code in this question is obviously contrived. I need this functionality for a testing utility that takes "snapshots" of structs of any type at different stages before various mutations are applied.
...
func process(i interface{}) (interface{}, error) {
value := reflect.ValueOf(i)
if value.Kind() == reflect.Ptr {
i = value.Elem().Interface()
}
return copystructure.Copy(i)
}
...
I try to convert interface{} to struct person...
package main
import (
"encoding/json"
"fmt"
)
func FromJson(jsonSrc string) interface{} {
var obj interface{}
json.Unmarshal([]byte(jsonSrc), &obj)
return obj
}
func main() {
type person struct {
Name string
Age int
}
json := `{"Name": "James", "Age": 22}`
actualInterface := FromJson(json)
fmt.Println("actualInterface")
fmt.Println(actualInterface)
var actual person
actual = actualInterface // error fires here -------------------------------
// -------------- type assertion always gives me 'not ok'
// actual, ok := actualInterface.(person)
// if ok {
// fmt.Println("actual")
// fmt.Println(actual)
// } else {
// fmt.Println("not ok")
// fmt.Println(actual)
// }
}
... But got error:
cannot use type interface {} as type person in assignment: need type assertion
To solve this error I tried to use type assertion actual, ok := actualInterface.(person) but always got not ok.
Playground link
The usual way to handle this is to pass a pointer to the output value to your decoding helper function. This avoids type assertions in your application code.
package main
import (
"encoding/json"
"fmt"
)
func FromJson(jsonSrc string, v interface{}) error {
return json.Unmarshal([]byte(jsonSrc), v)
}
func main() {
type person struct {
Name string
Age int
}
json := `{"Name": "James", "Age": 22}`
var p person
err := FromJson(json, &p)
fmt.Println(err)
fmt.Println(p)
}
Your problem is that you're creating an empty interface to begin with, and telling json.Unmarshal to unmarshal into it. While you've defined a person type, json.Unmarshal has no way of knowing that that's what you intend the type of the JSON to be. To fix this, move the definition of person to the top level (that is, move it out of the body of main), and changeFromJson` to this:
func FromJson(jsonSrc string) interface{} {
var obj person{}
json.Unmarshal([]byte(jsonSrc), &obj)
return obj
}
Now, when you return obj, the interface{} that's returned has person as its underlying type. You can run this code on the Go Playground.
By the way, your code is a bit un-idiomatic. I left the original Playground link unmodified except for my corrections so that it wouldn't be needlessly confusing. If you're curious, here's a version that's cleaned up to be more idiomatic (including comments on why I made the changes I did).