V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
vhysug01
V2EX  ›  Go 编程语言

请教大佬, go 如何根据变量名获取该变量的数据

  •  
  •   vhysug01 · 2020-07-23 17:57:55 +08:00 · 3558 次点击
    这是一个创建于 1345 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如有

    const (
        A iota
        B
        C
        D
    )
    
    a := []string{"A", "B", "D"}
    

    如何获取 a 中每个元素的值。即得到 0 1 3

    之前想用 map,可是如果 cont 里是 A--Z 的话就非常麻烦了,有什么好的办法么

    11 条回复    2020-07-25 16:02:47 +08:00
    qiangmin
        1
    qiangmin  
       2020-07-23 18:00:11 +08:00
    key, value := range a ?
    linvon
        2
    linvon  
       2020-07-23 18:03:19 +08:00
    这种变量名对应不到的吧,编译后或许变量名就没了,可以试试用 struct 给成员变量打 tag,然后用 reflect 包反射 struct
    ll1615
        3
    ll1615  
       2020-07-23 18:16:36 +08:00 via Android
    如果是想要把 A-Z 映射到 0-25,可以类似这样 'D'-'A' -> 3
    Leigg
        4
    Leigg  
       2020-07-23 18:19:18 +08:00 via Android
    你是不是在想 eval ?
    vhysug01
        5
    vhysug01  
    OP
       2020-07-23 18:31:46 +08:00
    具体问题是,有 A - F 个权限,存库里的时候,为了后台方便查看,存的都是字符串'A' ... 'F'. 但是在实际用的使用,为了可以&& , 只能用 0 2 4 8 这种数字。现在的实现是使用 map,list,一个用来存 key value,一个用来做排序 然后代码越看越臭了
    zhujinliang
        6
    zhujinliang  
       2020-07-23 18:47:28 +08:00 via iPhone
    你这个场景键不多,遍历一下 list 就可以了
    davidyanxw
        7
    davidyanxw  
       2020-07-24 10:54:31 +08:00
    直觉是拿不到。
    const 常量,在编译后直接是字面量,无法获取到它的地址,因此无法通过反射拿到了。

    map 倒是可以实现。
    yiplee
        8
    yiplee  
       2020-07-24 11:10:01 +08:00   ❤️ 1
    可以用 stringer 自动生成,举个例子

    安装 stringer

    ```shell
    go get -u -a golang.org/x/tools/cmd/stringer
    ```

    **permission.go**

    ```golang
    package core

    import (
    "sort"
    "strings"
    )

    //go:generate stringer --type Permission

    type Permission int

    const (
    A Permission = iota
    B
    C
    D
    E
    F
    )

    func PermissionFromName(p string) (Permission, bool) {
    idx := strings.Index(_Permission_name, p)
    if idx < 0 {
    return 0, false
    }

    pos := sort.Search(len(_Permission_index), func(i int) bool {
    return _Permission_index[i] >= uint8(idx)
    })

    return Permission(pos), true
    }
    ```

    执行 go generate

    ```shell
    go generate ./...
    ```

    生成 **permission_string.go** 文件

    ```golang
    // Code generated by "stringer --type Permission"; DO NOT EDIT.

    package core

    import "strconv"

    func _() {
    // An "invalid array index" compiler error signifies that the constant values have changed.
    // Re-run the stringer command to generate them again.
    var x [1]struct{}
    _ = x[A-0]
    _ = x[B-1]
    _ = x[C-2]
    _ = x[D-3]
    _ = x[E-4]
    _ = x[F-5]
    }

    const _Permission_name = "ABCDEF"

    var _Permission_index = [...]uint8{0, 1, 2, 3, 4, 5, 6}

    func (i Permission) String() string {
    if i < 0 || i >= Permission(len(_Permission_index)-1) {
    return "Permission(" + strconv.FormatInt(int64(i), 10) + ")"
    }
    return _Permission_name[_Permission_index[i]:_Permission_index[i+1]]
    }
    ```

    最后,可以使用 Permission.String() 方法将 enum 转成 string,也可以用 PermissionFromName() 转回来。enum 有变动的时候,重新执行一下 go generate 重新生成代码即可。
    yiplee
        9
    yiplee  
       2020-07-24 11:10:36 +08:00
    不知道为啥 md 格式没生效啊
    yiplee
        10
    yiplee  
       2020-07-24 11:13:51 +08:00
    vhysug01
        11
    vhysug01  
    OP
       2020-07-25 16:02:47 +08:00
    感谢各位老哥了,这样看还是我的 map array 好用。。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4543 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:58 · PVG 17:58 · LAX 02:58 · JFK 05:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.