I am developing a method that will make a signature based in the type of private key that is passed as argument. To do that, I'm passing a *crypto.PrivateKey variable as argument. But the problem comes when I want to do a type assertion to use the argument.
func Sign(text string, privKey *crypto.PrivateKey) string{
if _, ok := (*privKey).(rsa.PrivateKey) //This is ok
if _, ok := (privKey).(*rsa.PrivateKey) //This is not ok 2
I guess I can do the first thing because if I use "*", the compiler think that it is an interface. But I don't know why I can't do the second thing, when it should be correct.
By the way, I need to use a variable of type *rsa.PrivateKey, I can do this this way:
privRsa, _ := (*privKey).(rsa.PrivateKey)
var priv *rsa.PrivateKey
priv = &privRsa
What I can not understand is why I can't directly convert the *crypto.PrivateKey into *rsa.PrivateKey, or if it exist a way to do that. I thing doing it the way I'm doing it right now would allocate new space in memory that I shouldn't if I want it to be efficient
crypto.PrivateKey is an interface. *crypto.PrivateKey is a pointer to an interface. You can use type-assertion on an interface to get the underlying value:
func Sign(text string, privKey crypto.PrivateKey) string{
if _, ok := privKey.(rsa.PrivateKey)
...
}
...
var pkey rsa.PrivateKey
Sign(text,pkey)
Here, the private key value in the interface is a copy of the rsa.PrivateKey.
If you pass the address of pkey, then, then the interface would have a pointer to the private key:
func Sign(text string, privKey crypto.PrivateKey) string{
if _, ok := privKey.(*rsa.PrivateKey)
...
}
...
var pkey rsa.PrivateKey
Sign(text,&pkey)
Related
I am writing a unit test to check equality of struct that contains func.
Here are my test code.
Go Palyround
When comparing, I used a func named GetFunctionName to get function's name for going.
func GetFunctionName(i interface{}) string {
fmt.Printf("type in GetFunctionName: %v\n", reflect.TypeOf(reflect.ValueOf(i)))
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}
Also a compare function was made.
func SelectCompareStruct(got interface{}, want interface{}) {
rvGot := reflect.ValueOf(got)
rtGot := rvGot.Type()
rvWant := reflect.ValueOf(want)
rtWant := rvWant.Type()
for i := 0; i < rtGot.NumField(); i++ {
fieldGot := rtGot.Field(i)
fieldWant := rtWant.Field(i)
valueGot := rvGot.FieldByName(fieldGot.Name)
valueWant := rvWant.FieldByName(fieldWant.Name)
fmt.Printf("type in SelectCompareStruct: %v\n", reflect.TypeOf(reflect.ValueOf(valueGot)))
// Works
gotFuncNameInner := runtime.FuncForPC(valueGot.Pointer()).Name()
wantFuncNameInner := runtime.FuncForPC(valueWant.Pointer()).Name()
fmt.Printf("gotFuncNameInner:\n\t\t\t%v\nwantFuncNameInner:\n\t\t\t%v\n", gotFuncNameInner, wantFuncNameInner)
// Does not work
gotFuncName := GetFunctionName(valueGot)
wantFuncName := GetFunctionName(valueWant)
fmt.Printf("gotFuncName:\n\t%v\n wantFuncName:\n\t%v\n", gotFuncName, wantFuncName)
}
}
You can see, when I write directly to get function's name, it works.
However, it does not work when using a func instead.
Although, both of which type that apply Pointer() method are reflect.Value type.
Yes, I can change input type of GetFunctionName to reflect.Value for working.
That's not good for other use cases. I want to make a function for getting name for versatility.
It will be beautiful to make input type interface{}.
Anyone have any idea why? And how to fix it?
The problem is that you are calling reflect.Value on a reflect.Value. Fix by removing the extra call to reflect.Value.
func GetFunctionName(v reflect.Value) string {
fmt.Printf("type in GetFunctionName: %v\n", v.Type())
return runtime.FuncForPC(v.Pointer()).Name()
}
Run it on the playground.
I would like to assign a value within a variable declaration of type struct, however, I need to call a function that returns a secondary value (an error) which I would like to disregard in the assignment.
Is there a way to do so? For example:
type myStruct struct{
address common.Address
}
func main() {
newVar := myStruct{
address: common.HexToAddress("xyz")
}
}
The issue is that common.HexToAddress() returns 2 values, a common.Address as well as an error. I would like to omit the error and assign it as above. I would prefer not to have to do:
var newVar2 myStruct
myStruct,_ = common.HexToAddress("xyz")
It's usually not exactly recommended to ignore errors, which may be one reason why the language does not make this easy.
That being said, a pattern you see sometimes is a package offering a Must function, for those cases where just doing a panic() on an error is the right thing to do; e.g., when initializing package-level variables.
For example, there's text/template.Must. The implementation simply tests the error and panics if it is not nil. You can consider adding such a function as well (possibly local to your file), allowing you to write your struct initialization as:
newVar := myStruct{
address: must(common.HexToAddress("xyz")),
}
// ...
func must(address common.Address, err error) common.Address { ... }
This relies on the feature that if a function returns multiple values, and another function takes the same amount of parameters, you can invoke the latter directly on the return values of the former.
If you don't want to go that far, you do need to explicitly ignore the second return value by assigning it to the blank identifier _. You could of course do that separately, so that you still get to use a structure literal, but it may not be any cleaner than what you suggested originally:
address, _ := common.HexToAddress("xyz")
newVar := myStruct{address: address}
You're probably looking for some kind of syntactic sugar. Go is intentionally sparse on such things, because in the opinion of the language designers, it tends to make things less obvoius, thus less readable. So you have limited options here.
If you really don't care about the error, here are your options:
Assign to a temporary variable as you suggested (usually the most natural/readable option):
addr, _ := common.HexToAddress("xyz")
newVar := myStruct{
address: addr,
}
Use the return value of an anonymous function:
newVar := myStruct{
address: func() common.Address { addr, _ := common.HexToAddress("xyz"); return addr }(),
}
If you control the common package, consider adding a variant that ignores (or panics on) errors:
newVar := myStruct{
address: common.MustHexToAddress("xyz"),
}
Write your own wrapper function:
func hexToAddress(hex string) common.Address {
addr, _ := common.HexToAddress(hex)
return addr
}
newVar := myStruct{
address: hexToAddress("xyz"),
}
Given a function with a parameter (that is a pointer to a struct) I want to instantiate a type of this parameter.
For example, for this function:
func MyFunction(myStruct *MyStruct) {}
using reflection I want to create a variable that contains exactly same as x := &MyStruct{} would contain.
This is the code example:
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
}
func main () {
reflectedFunction := reflect.TypeOf(MyFunction)
argType := reflectedFunction.In(0)
reflectedParameter := reflect.New(argType)
actual := reflectedParameter.Interface()
fmt.Println(actual)
expected := &MyStruct{}
fmt.Println(expected)
}
func MyFunction(myStruct *MyStruct) {
}
If you execute it, you'll see that they contain different info:
0xc00000e028 // actual
&{} // expected
This question isn't about why I would like to do this, so please avoid recommending not doing it, etc.
In your code, actual is a interface{} value containing a *MyStruct. As the name and documentation indicate, reflectedParameter.Interface() returns an interface{}.
using reflection I want to create a variable that contains exactly same as x := &MyStruct{} would contain.
Then you'll have to type assert it:
actual := reflectedParameter.Elem().Interface().(*MyStruct)
reflect.New creates a pointer to a new zero value of the reflected type. In your example that type is already a *MyStruct, so the value of your actual winds up being a representation of a **MyStruct, as seen in https://play.golang.org/p/Nyuc0mYmgkZ. Taking the .Elem() of that results in the correct type again, but you end up with a nil pointer (*MyStruct)(nil).
You need to take the .Elem() if that first type if you want to create a new pointer value.
reflectedParameter := reflect.New(argType.Elem())
https://play.golang.org/p/QzwTFUH3HTs
reflectedFunction := reflect.TypeOf(MyFunction)
argType := reflectedFunction.In(0)
reflectedParameter := reflect.New(argType.Elem())
actual := reflectedParameter.Interface()
fmt.Printf("%#v\n", actual)
expected := &MyStruct{}
fmt.Printf("%#v\n", expected)
Which prints
&main.MyStruct{}
&main.MyStruct{}
I'm trying to import my own RSA public key as opposed to generating one to encrypt a string with. Only thing is that I'm having issues changing to the correct type. Here's my current code:
func main() {
s := ""
i := new(big.Int)
i.SetString(s, 16)
encrypt(i)
}
func encrypt(i *big.Int) {
publicKey := PublicKey{N: i, E: 010001}
secretMessage := "This is super secret message!"
encryptedMessage := RSA_OAEP_Encrypt(secretMessage, publicKey)
fmt.Println("Cipher Text:", encryptedMessage)
}
Where it doesn't like publicKey's type
What I'm wondering is if there's a way that I can **convert type PublicKey** to **type rsa.PublicKey** so that I can use it for encryption.
There seem to be two types of key: one is the base interface, called just PublicKey. The type rsa.PublicKey is derived from that and should be used instead. Otherwise the key type is not set correctly and the code will fail. I presume it creates an anonymous type with the values set.
I am pretty new to go and I was playing with this notify package.
At first I had code that looked like this:
func doit(w http.ResponseWriter, r *http.Request) {
notify.Post("my_event", "Hello World!")
fmt.Fprint(w, "+OK")
}
I wanted to append newline to Hello World! but not in the function doit above, because that would be pretty trivial, but in the handler afterwards like this below:
func handler(w http.ResponseWriter, r *http.Request) {
myEventChan := make(chan interface{})
notify.Start("my_event", myEventChan)
data := <-myEventChan
fmt.Fprint(w, data + "\n")
}
After go run:
$ go run lp.go
# command-line-arguments
./lp.go:15: invalid operation: data + "\n" (mismatched types interface {} and string)
After a little bit of Googling I found this question on SO.
Then I updated my code to:
func handler(w http.ResponseWriter, r *http.Request) {
myEventChan := make(chan interface{})
notify.Start("my_event", myEventChan)
data := <-myEventChan
s:= data.(string) + "\n"
fmt.Fprint(w, s)
}
Is this what I was supposed to do? My compiler errors are gone so I guess that's pretty good? Is this efficient? Should you do it differently?
According to the Go specification:
For an expression x of interface type and a type T, the primary expression x.(T) asserts that x is not nil and that the value stored in x is of type T.
A "type assertion" allows you to declare an interface value contains a certain concrete type or that its concrete type satisfies another interface.
In your example, you were asserting data (type interface{}) has the concrete type string. If you are wrong, the program will panic at runtime. You do not need to worry about efficiency, checking just requires comparing two pointer values.
If you were unsure if it was a string or not, you could test using the two return syntax.
str, ok := data.(string)
If data is not a string, ok will be false. It is then common to wrap such a statement into an if statement like so:
if str, ok := data.(string); ok {
/* act on str */
} else {
/* not string */
}
Type Assertion
This is known as type assertion in golang, and it is a common practice.
Here is the explanation from a tour of go:
A type assertion provides access to an interface value's underlying concrete value.
t := i.(T)
This statement asserts that the interface value i holds the concrete type T and assigns the underlying T value to the variable t.
If i does not hold a T, the statement will trigger a panic.
To test whether an interface value holds a specific type, a type assertion can return two values: the underlying value and a boolean value that reports whether the assertion succeeded.
t, ok := i.(T)
If i holds a T, then t will be the underlying value and ok will be true.
If not, ok will be false and t will be the zero value of type T, and no panic occurs.
NOTE: value i should be interface type.
Pitfalls
Even if i is an interface type, []i is not interface type. As a result, in order to convert []i to its value type, we have to do it individually:
// var items []i
for _, item := range items {
value, ok := item.(T)
dosomethingWith(value)
}
Performance
As for performance, it can be slower than direct access to the actual value as show in this stackoverflow answer.
//an easy way:
str := fmt.Sprint(data)
As asked for by #ρяσѕρєя an explanation can be found at https://golang.org/pkg/fmt/#Sprint. Related explanations can be found at https://stackoverflow.com/a/44027953/12817546 and at https://stackoverflow.com/a/42302709/12817546. Here is #Yuanbo's answer in full.
package main
import "fmt"
func main() {
var data interface{} = 2
str := fmt.Sprint(data)
fmt.Println(str)
}
In addition to other answers, I think it's good to have a look at "type switch":
package main
import "fmt"
func printType(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("type of %v is %v\n", i, v)
// type of 21 is int
case string:
fmt.Printf("type of %v is %v\n", i, v)
// type of hello is string
default:
fmt.Printf("type of %v is %v\n", i, v)
// type of true is bool
}
}
func main() {
printType(21)
printType("hello")
printType(true)
}
I hope it helps.
More information: https://go.dev/tour/methods/16