Name of a constant given its value

前端 未结 3 808
名媛妹妹
名媛妹妹 2021-02-01 04:10

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 packa

相关标签:
3条回答
  • 2021-02-01 04:42

    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`,
        ...
    }
    
    0 讨论(0)
  • 2021-02-01 04:58

    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.

    0 讨论(0)
  • 2021-02-01 05:04

    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.

    0 讨论(0)
提交回复
热议问题