I am using a package: ccs08
In my main, I am importing the package and using some of its functions. I have followed the usage from the unit tests given:
package main
import(
"fmt"
"math/big"
"crypto/rand"
"zkrp/ccs08"
"zkrp/crypto/bn256"
)
func main(){
var (
r *big.Int
s []int64
)
s = make([]int64, 4)
s[0] = 12
s[1] = 42
s[2] = 61
s[3] = 71
p, _ := ccs08.SetupSet(s)
r, _ = rand.Int(rand.Reader, bn256.Order)
proof_out, _ := ccs08.ProveSet(12, r, p)
result, _ := ccs08.VerifySet(&proof_out, &p)
if result != true {
fmt.Println("not verified")
}
}
I then have a similar main file,main2, where I am using another set of functions from the same package. This does NOT work
package main
import(
"fmt"
"math/big"
"crypto/rand"
"zkrp/ccs08"
"zkrp/crypto/bn256"
)
func main(){
var (
result bool
zkrp ccs08
)
zkrp.Setup(347184000, 599644800)
zkrp.x = new(big.Int).SetInt64(419835123)
zkrp.r, _ = rand.Int(rand.Reader, bn256.Order)
e := zkrp.Prove()
result, _ = zkrp.Verify()
if result != true {
fmt.println("not verified")
}
}
I am getting this error:
./main2.go:7: imported and not used: "zkrp/ccs08".
./main2.go:16: use of package ccs08 without selector.
What am I doing wrong?
For the first file, everything works because the code is using public members of the ccs08 package. However, this is not the case for the second file.
You mentioned the code in the second file is copied from here.
To understand why the code does not work when pasted into a main method outside the ccs08 package, you need to understand what it is doing in its original location. Specifically this part:
var (
result bool
zkrp ccs08
)
In the original location (inside the ccs08 package) there is a private struct type named ccs08. The declaration can be seen here. What the above code is doing is creating a variable named zkrp the type of which is the private struct type ccs08. Then, the various functions called on the variable are methods bound to this private struct (you can see the methods here).
Now, in the code you posted (after pasting into a location outside the ccs08 package), there is no way to access the private ccs08 struct (I can't even find a public method which returns it in the zkrp source code). So, what Go sees when it tries to execute this code is a typo (where it thinks you are trying to write something of the form package.Member):
// this looks like you wanted to declare a variable with type:
// "ccs08.SomeType" but forgot to write ".SomeType"
// Thus Go gives the error: "use of package ccs08 without selector"
var zkrp ccs08
And the "imported and not used" error is because the ccs08 package isn't used in a valid way anywhere in the code.
The code which you copied is honestly pretty confusing with all the reusing of the strings ccs08 and zkrp for naming of different things. I hope this clears it up a bit.
Related
I have defined a constant with a type. I want to use the value of a variable to refer to the constant. (Please refer to the code below).
One way would be to define a map of Key to the required Value. Is there another approach to do this ?
import (
"fmt"
"reflect"
)
type Code int
const (
MY_CONST_KEY Code = 123
)
func main() {
x := "MY_CONST_KEY"
//Fetch Value of x as 123
}
There is no way to do what you are asking. You cannot pass constants to the reflect package without instead passing their literal value.
As you correctly mentioned, you can use a map:
package main
import "fmt"
type Code int
var codes = map[string]Code{
"MY_CONST_KEY": 123,
"ANOTHER_CONST_KEY": 456,
}
func main() {
x := codes["MY_CONST_KEY"]
fmt.Println(x)
}
If you make sure the map is not exported (lower case c in codes), then it will only be available inside your package, so consumers of your package cannot modify the map at runtime.
Instead of assigning x to a string, "MY_CONST_KEY", you can do x := MY_CONST_KEY
package main
import (
"fmt"
)
type Code int
const (
MY_CONST_KEY Code = 123
)
func main() {
x := MY_CONST_KEY
fmt.Println(x) // This fetch the value of x as 123
}
One way would be to define a map of Key to the required Value.
Yes, do that.
Is there another approach to do this ?
No.
I was taking a look at the publicsuffix library in Go and found it pretty useful in extracting domains out of strings. This is what I have:
package main
import (
"fmt"
"golang.org/x/net/publicsuffix"
)
func main() {
url := "a.very.complex-domain.co.uk"
u, _ := publicsuffix.EffectiveTLDPlusOne(url)
fmt.Printf(u)
}
This works fine yeilding complex-domain.co.uk as the valid domain. However, the problem I am facing is when any random string is passed to the function (containing a dot), the library gives out a valid domain name anyhow (even if the TLD doesn't exist in the publicsuffix list).
package main
import (
"fmt"
"golang.org/x/net/publicsuffix"
)
func main() {
url := "a.very.complex-domain.someinvalidtld"
u, _ := publicsuffix.EffectiveTLDPlusOne(url)
fmt.Printf(u)
}
Gives: complex-domain.someinvalidtld
My understanding is that the publicsuffix package assumes that it is a local domain and parses it anyhow. Is there a way to avoid this behavior and extract only valid ones out?
I figured it out, you can easily do it using the same library:
func checkForValidTLD(str string) bool {
etld, im := publicsuffix.PublicSuffix(str)
var validtld = false
if im { // ICANN managed
validtld = true
} else if strings.IndexByte(etld, '.') >= 0 { // privately managed
validtld = true
}
return validtld
}
So calling the function like:
if checkForValidTLD("a.very.complex-domain.someinvalidtld") {
fmt.Println("Valid")
} else {
fmt.Println("Invalid")
}
Returns: Invalid.
The logic behind this is: For all TLDs that aren't ICANN managed, if they have a . in them, it means that they are privately managed (e.g. blogspot.co.uk), otherwise it is invalid TLD.
Given a code setup like this,
package main
import (
"fmt"
"reflect"
"runtime/debug"
)
type A struct{}
func (o *A) B() error {
debug.PrintStack()
return nil
}
func main() {
a := &A{}
b := a.B
// Note that if run b(), it can print the stack and show the info
// "(*A).B-fm" and "(*A).B"
m := reflect.ValueOf(b)
fmt.Println(m.Type().String())
}
Is it possible to get the information of b's receiver type A and B as a method? How if possible?
Note that b is value of method B of type A.
(Possible use scenario, generating a constant unique API ID based on only a reference like b, by forming a string like (*A).B. It's used to build a debug tool without a need to change existing code.)
update:
This will do the work.
fmt.Println(runtime.FuncForPC(m.Pointer()).Name())
Credits to this awesome article,
I was wondering if it was possible to not know a function name but call it anyway and get values from it. This lead me to the reflection package and I got pretty close but I’m not sure about the last step - if there is one. Again please forgive me if I am missing something obvious, this is my first attempt at doing anything in Go other than getting it setup.
Of course being a compiled language there is no need to iterate through things to find function names, I know them all, but this is something I want to see if it is possible… I’m playing and learning.
Below is the code. What I would really like to do is in the main line extract the values set in ModuleBoot() <“1.0012”, 23> and SomethingBoot() <“1.0000”, 10> but so far all as I can get is structure information. Perhaps that’s just the way it is but perhaps there is a step or change that can make it go the next step.
Hopefully I copied all the relevant code over correctly so it compiles as is:
// Using: go version go1.9.7 linux/amd64
=======================================
FILE: main.go
=======================================
package main
import (
"fmt"
"reflect"
"playing/modules/core"
)
func main() {
miType := reflect.TypeOf(core.ModuleInfo{})
fmt.Println("")
for i := 0; i < miType.NumMethod(); i++ {
method := miType.Method(i)
fmt.Println(method.Name)
in := make([]reflect.Value, method.Type.NumIn())
in[0] = reflect.ValueOf(core.ModuleInfo{})
//fmt.Println("Params in:", method.Type.NumIn(), "Params out:", method.Type.NumOut())
mi := method.Func.Call(in)
fmt.Println("mi:", mi)
fmt.Println("")
}
}
=======================================
FILE: playing/modules/core/something.go
=======================================
package core
func (mi ModuleInfo) SomethingBoot() ModuleInfo {
mi.Version = "1.0000"
mi.Priority = 10
return mi
}
=======================================
FILE: playing/modules/core/modules.go
=======================================
package core
type ModuleInfo struct {
Version string
Priority int
}
func (mi ModuleInfo) ModuleBoot() ModuleInfo {
mi.Version = "1.0012"
mi.Priority = 23
return mi
}
The output I got from this was:
Started delve with config "Debug"
SomethingBoot
mi: [<core.ModuleInfo Value>]
ModuleBoot
mi: [<core.ModuleInfo Value>]
delve closed with code 0
To get the return value as a ModuleInfo, get the underlying value of the first return value and type assert that interface value to ModuleInfo:
// mi has type core.ModuleInfo
mi := method.Func.Call(in)[0].Interface().(core.ModuleInfo)
Run it on the Playground.
You can cut some of the reflect code by type asserting the method to a function with the correct signature and calling that function directly:
for i := 0; i < miType.NumMethod(); i++ {
method := miType.Method(i).Func.Interface().(func(core.ModuleInfo) core.ModuleInfo)
mi := method(core.ModuleInfo{})
fmt.Println("Version", mi.Version)
fmt.Println("Priority", mi.Priority)
fmt.Println("")
}
Run it on the Playground
Go natively supports functions as values; you don't need reflection to do this.
In particular, if you make your two functions top-level functions (not specifically tied to a struct):
package core
type ModuleInfo struct { ... }
func SomethingBoot() ModuleInfo
func ModuleBoot() ModuleInfo
Then you can write a function that takes a function as a parameter:
func PrintVersion(func booter() core.ModuleInfo) {
mi := booter()
fmt.Printf("version %s\n", mi.Version)
}
And you can just pass the pre-existing functions as parameters:
PrintVersion(core.SomethingBoot)
PrintVersion(core.ModuleBoot)
Notice that there aren't parentheses after the function name: you are passing the function itself as a parameter, not calling the function and passing its return value.
I am curious if this type of declaration for structs
t := Person{"girlie", 12}
only works if its type is declared in the same file.
Below are my files.
file st.go, type def structure inside to be used in main func
package structs
type person struct {
age int
name int
}
file practice.go, main function:
package main
import(
"fmt"
"structs/dir"
)
func main() {
var s dir.Person
s.Name = "She"
s.Age = 12
>> t := Person{"girlie", 12}
fmt.Println(s.Name)
fmt.Println(t.Name)
}
As you can see an error occurs where instance t is declared.
You're missing the package reference, it should be:
t := dir.Person{"girlie", 12}
// ^^^^ missing this part
Assuming that the line var s dir.Person works, which I'm guessing it does based on the question, which means that your quoted contents of "st.go" are not accurate, because the package name is different, and the struct and its fields are not exported.