How do you get the name of a constant given its value ?
More specifically (and to get a more readable understanding), I'm working with the crypto/tls
package. Cipher suites are defined as constants:
const (
TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
)
After a successful handshake with a server, I can get to the Ciphersuite agreed on through the connection:
c, _ := tls.Dial("tcp", "somedomain.com:443", nil)
// Suppose everything went right
// This is the Ciphersuite for the conn:
cipher := c.ConnectionState().Ciphersuite
cipher
here is an uint16. Is there a way to display it as a string, for instance TLS_RSA_WITH_3DES_EDE_CBC_SHA
if that's what was agreed upon ?
Syntax to assign a constant value in java:static final datatype identifier_name = constant; The static modifier causes the variable to be available without an instance of it's defining class being loaded. The final modifier makes the variable unchangeable.
A constant variable is one whose value cannot be updated or altered anywhere in your program. A constant variable must be initialized at its declaration.
Constant: A constant can be defined as a fixed value, which is used in algebraic expressions and equations. A constant does not change over time and has a fixed value. For example, the size of a shoe or cloth or any apparel will not change at any point.
Note: As of Go 1.4, the String()
code below can be auto-generated using Go's new generate
feature, combined with the stringer
command. See here for more info.
Apart from ANisus' answer, you can do the following.
package main
import "fmt"
import "crypto/tls"
type Ciphersuite uint16
const (
TLS_RSA_WITH_RC4_128_SHA = Ciphersuite(tls.TLS_RSA_WITH_RC4_128_SHA)
TLS_RSA_WITH_3DES_EDE_CBC_SHA = Ciphersuite(tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA)
TLS_RSA_WITH_AES_128_CBC_SHA = Ciphersuite(tls.TLS_RSA_WITH_AES_128_CBC_SHA)
TLS_RSA_WITH_AES_256_CBC_SHA = Ciphersuite(tls.TLS_RSA_WITH_AES_256_CBC_SHA)
TLS_ECDHE_RSA_WITH_RC4_128_SHA = Ciphersuite(tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA)
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = Ciphersuite(tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = Ciphersuite(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = Ciphersuite(tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
)
func (cs Ciphersuite) String() string {
switch cs {
case TLS_RSA_WITH_RC4_128_SHA:
return "TLS_RSA_WITH_RC4_128_SHA"
case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
case TLS_RSA_WITH_AES_128_CBC_SHA:
return "TLS_RSA_WITH_AES_128_CBC_SHA"
case TLS_RSA_WITH_AES_256_CBC_SHA:
return "TLS_RSA_WITH_AES_256_CBC_SHA"
case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"
case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"
}
return "Unknown"
}
func main() {
cs := TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
fmt.Printf("0x%04x = %s\n", uint16(cs), cs)
cs = TLS_RSA_WITH_RC4_128_SHA
fmt.Printf("0x%04x = %s\n", uint16(cs), cs)
cs = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
fmt.Printf("0x%04x = %s\n", uint16(cs), cs)
}
You can test it on the go playground.
I am afraid that is not possible.
The constants are resolved at compile time and there is nothing in the reflect
package that allows you to retrieve the name.
What I suggest is creating a map with the names:
var constLookup = map[uint16]string{
tls.TLS_RSA_WITH_RC4_128_SHA: `TLS_RSA_WITH_RC4_128_SHA`,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: `TLS_RSA_WITH_3DES_EDE_CBC_SHA`,
...
}
You can use go generate
to have this generated for you.
Install stringer
using
go get golang.org/x/tools/cmd/stringer
Now define a type
for your const
. You can do it like this
type TLSType uint16
const (
TLS_RSA_WITH_RC4_128_SHA TLSType = 0x0005
TLS_RSA_WITH_3DES_EDE_CBC_SHA TLSType = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA TLSType = 0x002f
TLS_RSA_WITH_AES_256_CBC_SHA TLSType = 0x0035
TLS_ECDHE_RSA_WITH_RC4_128_SHA TLSType = 0xc011
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA TLSType = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLSType = 0xc013
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA TLSType = 0xc014
)
Then add this line to your file (spacing is important)
//go:generate stringer -type=TLSType
Now go to the terminal in the folder where your program is and run
go generate
This will create a file called tlstype_string.go
in your code directory, which is the generated code that implements the fmt.Stringer
interface for your TLSType
. Open it if you want to see the implementation but you don't need to. It will just work.
Now when you run go build
or go run *.go
on this directory, your source files will use the generated code.
The full program would look something like this
package main
import (
"fmt"
)
//go:generate stringer -type=TLSType
type TLSType uint16
const (
TLS_RSA_WITH_RC4_128_SHA TLSType = 0x0005
TLS_RSA_WITH_3DES_EDE_CBC_SHA TLSType = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA TLSType = 0x002f
TLS_RSA_WITH_AES_256_CBC_SHA TLSType = 0x0035
TLS_ECDHE_RSA_WITH_RC4_128_SHA TLSType = 0xc011
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA TLSType = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLSType = 0xc013
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA TLSType = 0xc014
)
func main() {
fmt.Println("This const will be printed with its name instead of its number:")
fmt.Println(TLS_RSA_WITH_RC4_128_SHA)
fmt.Println()
fmt.Println("So will this one:")
fmt.Println(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
fmt.Println()
fmt.Println("Or maybe we want to give it a value and convert:")
fmt.Println(TLSType(0xc011))
fmt.Println()
fmt.Println("No problem:")
fmt.Println(TLSType(0xc013))
}
Which outputs
This const will be printed with its name instead of its number:
TLS_RSA_WITH_RC4_128_SHA
So will this one:
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Or maybe we want to give it a value and convert:
TLS_ECDHE_RSA_WITH_RC4_128_SHA
No problem:
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
If you add new const
values, just run go generate
again to update the generated code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With