Use a literal value to refer to constant in Golang - go

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.

Related

How to resolve "use of package without a selector error"

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.

Is byte slice in Golang a 2d data structure

I got this code off some blog, I want to know why the reassignment of a particular index in the slice b is denoted using a 2d indexing, example
b[0][0] = byte('*')
Isn't it supposed to be
b[0]=byte('*')
package main
import (
"bytes"
"fmt"
)
func splitDemo() {
fmt.Println("Split demo")
a := []byte("a,b,c")
b := bytes.Split(a, []byte(","))
b[0][0] = byte('*')
fmt.Printf("%q",b)
fmt.Printf("%q",a)
}
func main() {
splitDemo()
}
bytes.Split returns a [][]byte. That's a slice of []byte.

Why this repeats the same random number?

I'm new to Go and not sure why it prints the same number for rand.Intn(n int) int for every run:
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println(rand.Intn(10))
}
The docs says :
Intn returns, as an int, a non-negative pseudo-random number in [0,n) from the default Source. It panics if n <= 0.
And how do I properly seed the random number generation?
By calling the rand.Seed() function, passing it a (random) seed (typically the current unix timestamp). Quoting from math/rand package doc:
Top-level functions, such as Float64 and Int, use a default shared Source that produces a deterministic sequence of values each time a program is run. Use the Seed function to initialize the default Source if different behavior is required for each run.
Example:
rand.Seed(time.Now().UnixNano())
If rand.Seed() is not called, the generator behaves as if seeded by 1:
Seed uses the provided seed value to initialize the default Source to a deterministic state. If Seed is not called, the generator behaves as if seeded by Seed(1).
package main
import
(
"fmt"
"math/rand"
"time"
)
func randomGen(min, max int) int {
rand.Seed(time.Now().Unix())
return rand.Intn(max - min) + min
}
func main() {
randNum := randomGen(1, 10)
fmt.Println(randNum)
}
Under the package, math/rand, you can find a type Rand.
func New(src Source) *Rand - New returns a new Rand that uses random
values from src to generate other random values.
It actually needs a seed to generate it.
step 1: create a seed as a source using new Source.
time.Now().UnixNano() is used for the accuracy.
step 2: create a
type Rand from the seed
step 3: generate a random number.
Example:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
source := rand.NewSource(time.Now().UnixNano())
r := rand.New(source)
fmt.Println(r.Intn(100))
}

What's the difference between new(Struct) and &Struct{} in Go?

They seem to be the same:
package main
import "fmt"
type S struct {
i int
}
func main() {
var s1 *S = new(S)
fmt.Println(s1)
var s2 *S = &S{}
fmt.Println(s2) // Prints the same thing.
}
Update:
Hm. I just realized that there's no obvious way to initialize S.i using new. Is there a way to do that? new(S{i:1}) does not seem to work :/
From Effective Go:
As a limiting case, if a composite literal contains no fields at all, it creates a zero value for the type. The expressions new(File) and &File{} are equivalent.
Not only do they give the same resulting value, but if we allocate something both ways and look at their values...
// Adapted from http://tour.golang.org/#30
package main
import "fmt"
type Vertex struct {
X, Y int
}
func main() {
v := &Vertex{}
v2 := new(Vertex)
fmt.Printf("%p %p", v, v2)
}
...we'll see that they are in fact allocated in consecutive memory slots. Typical output: 0x10328100 0x10328108. I'm not sure if this is an implementation detail or part of the specification, but it does demonstrate that they're both being allocated from the same pool.
Play around with the code here.
As for initializing with new, according to the language spec: The built-in function new takes a type T and returns a value of type *T. The memory [pointed to] is initialized as described in the section on initial values. Because functions in go can't be overloaded, and this isn't a variadic function, there's no way to pass in any initialization data. Instead, go will initialize it with whatever version of 0 makes sense for the type and any member fields, as appropriate.
Case 1: package main
import (
"fmt"
)
type Drink struct {
Name string
Flavour string
}
func main() {
a := new(Drink)
a.Name = "Maaza"
a.Flavour = "Mango"
b := a
fmt.Println(&a)
fmt.Println(&b)
b.Name = "Frooti"
fmt.Println(a.Name)
}//This will output Frooti for a.Name, even though the addresses for a and b are different.
Case 2:
package main
import (
"fmt"
)
type Drink struct {
Name string
Flavour string
}
func main() {
a := Drink{
Name: "Maaza",
Flavour: "Mango",
}
b := a
fmt.Println(&a)
fmt.Println(&b)
b.Name = "Froti"
fmt.Println(a.Name)
}//This will output Maaza for a.Name. To get Frooti in this case assign b:=&a.

Using reflect, how do you set the value of a struct field?

having a rough time working with struct fields using reflect package. in particular, have not figured out how to set the field value.
type t struct { fi int; fs string }
var r t = t{ 123, "jblow" }
var i64 int64 = 456
getting Name of field i - this seems to work
var field = reflect.TypeOf(r).Field(i).Name
getting value of field i as a) interface{}, b) int - this seems to work
var iface interface{} = reflect.ValueOf(r).Field(i).Interface()
var i int = int(reflect.ValueOf(r).Field(i).Int())
setting value of field i - try one - panic
reflect.ValueOf(r).Field(i).SetInt( i64 )
panic: reflect.Value·SetInt using value obtained using unexported field
assuming it did not like field names "id" and "name", so renamed to "Id" and "Name"
a) is this assumption correct?
b) if correct, thought not necessary since in same file / package
setting value of field i - try two (with field names capitalized ) - panic
reflect.ValueOf(r).Field(i).SetInt( 465 )
reflect.ValueOf(r).Field(i).SetInt( i64 )
panic: reflect.Value·SetInt using unaddressable value
Instructions below by #peterSO are thorough and high quality
Four. this works:
reflect.ValueOf(&r).Elem().Field(i).SetInt( i64 )
he documents as well that the field names must be exportable (begin with capital letter)
The Go json package marshals and unmarshals JSON from and to Go structures.
Here's a step-by-step example which sets the value of a struct field while carefully avoiding errors.
The Go reflect package has a CanAddr function.
func (v Value) CanAddr() bool
CanAddr returns true if the value's
address can be obtained with Addr.
Such values are called addressable. A
value is addressable if it is an
element of a slice, an element of an
addressable array, a field of an
addressable struct, or the result of
dereferencing a pointer. If CanAddr
returns false, calling Addr will
panic.
The Go reflect package has a CanSet function, which, if true, implies that CanAddr is also true.
func (v Value) CanSet() bool
CanSet returns true if the value of v
can be changed. A Value can be changed
only if it is addressable and was not
obtained by the use of unexported
struct fields. If CanSet returns
false, calling Set or any
type-specific setter (e.g., SetBool,
SetInt64) will panic.
We need to make sure we can Set the struct field. For example,
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
// N at start
fmt.Println(n.N)
// pointer to struct - addressable
ps := reflect.ValueOf(&n)
// struct
s := ps.Elem()
if s.Kind() == reflect.Struct {
// exported field
f := s.FieldByName("N")
if f.IsValid() {
// A Value can be changed only if it is
// addressable and was not obtained by
// the use of unexported struct fields.
if f.CanSet() {
// change value of N
if f.Kind() == reflect.Int {
x := int64(7)
if !f.OverflowInt(x) {
f.SetInt(x)
}
}
}
}
}
// N at end
fmt.Println(n.N)
}
Output:
42
7
If we can be certain that all the error checks are unnecessary, the example simplifies to,
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
fmt.Println(n.N)
reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7)
fmt.Println(n.N)
}
BTW, Go is available as open source code. A good way to learn about reflection is to see how the core Go developers use it. For example, the Go fmt and json packages. The package documentation has links to the source code files under the heading Package files.
This seems to work:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
Number int
Text string
}
func main() {
foo := Foo{123, "Hello"}
fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))
reflect.ValueOf(&foo).Elem().Field(0).SetInt(321)
fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))
}
Prints:
123
321

Resources