英文:
Name of a constant given its value
问题
如何根据常量的值获取其名称?
更具体地说(为了更好地理解),我正在使用crypto/tls
包。密码套件被定义为常量:
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
)
在与服务器成功握手之后,我可以通过连接获取协商的密码套件:
c, _ := tls.Dial("tcp", "somedomain.com:443", nil)
// 假设一切顺利
// 这是连接的密码套件:
cipher := c.ConnectionState().Ciphersuite
这里的cipher
是一个uint16
类型的值。是否有办法将其显示为字符串,例如,如果协商的密码套件是TLS_RSA_WITH_3DES_EDE_CBC_SHA
,那么能否将其显示为该字符串?
英文:
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 ?
答案1
得分: 32
注意:从Go 1.4版本开始,可以使用Go的新“generate”功能自动生成下面的String()
代码,结合stringer
命令使用。在这里了解更多信息。
除了ANisus的答案,你还可以进行以下操作。
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)
}
你可以在Go Playground上测试它。
英文:
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.
答案2
得分: 24
很抱歉,我不能提供代码翻译服务。但是,我可以帮你解释这段代码的含义。
这段代码中,作者想要获取常量的名称。然而,在编译时,常量的值已经被解析,而reflect
包中没有提供任何方法来获取常量的名称。
作者建议创建一个包含常量名称的映射(map),以便在需要时进行查找。示例代码如下:
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`,
...
}
通过使用这个映射,你可以通过常量的值来获取对应的名称。
英文:
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`,
...
}
答案3
得分: 24
你可以使用go generate
来自动生成代码。
首先使用以下命令安装stringer
:
go get golang.org/x/tools/cmd/stringer
然后定义一个const
类型,可以像这样进行定义:
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
)
然后在你的文件中添加以下代码(注意空格的位置):
//go:generate stringer -type=TLSType
现在在终端中进入你的程序所在的文件夹,并运行以下命令:
go generate
这将在你的代码目录中创建一个名为tlstype_string.go
的文件,这个文件是为你的TLSType
类型实现了fmt.Stringer
接口的生成代码。如果你想查看实现细节,可以打开这个文件,但这不是必需的,它会自动工作。
现在当你在该目录下运行go build
或go run *.go
时,你的源文件将使用生成的代码。
完整的程序看起来像这样:
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("这个const将会以它的名称而不是它的数值打印出来:")
fmt.Println(TLS_RSA_WITH_RC4_128_SHA)
fmt.Println()
fmt.Println("这个也是一样:")
fmt.Println(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
fmt.Println()
fmt.Println("或者我们想给它一个值并进行转换:")
fmt.Println(TLSType(0xc011))
fmt.Println()
fmt.Println("没有问题:")
fmt.Println(TLSType(0xc013))
}
运行结果如下:
这个const将会以它的名称而不是它的数值打印出来:
TLS_RSA_WITH_RC4_128_SHA
这个也是一样:
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
或者我们想给它一个值并进行转换:
TLS_ECDHE_RSA_WITH_RC4_128_SHA
没有问题:
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
如果你添加了新的const
值,只需再次运行go generate
命令来更新生成的代码。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论