缺乏对数组常量的支持的解决方法?

huangapple go评论114阅读模式
英文:

Workaround for lack of support for array constants?

问题

Go语言没有数组常量。

我的应用程序接收包含多种类型的数字代码的消息,我需要将其显示为短语。

如果存在数组常量,我可以这样做:

  1. func foo() {
  2. ...
  3. fmt.Println(facename[f])
  4. ...
  5. }
  6. const facename [...]string = "top", "bottom", "left", "right", "front", "back"

但是当然没有办法这样做。我能想到的第一种解决方法,也许是一种合理高效的方法,是使用switch语句:

  1. func foo() {
  2. ...
  3. name := "unknown"
  4. switch f {
  5. case 0:
  6. name = "top"
  7. case 1:
  8. name = "bottom"
  9. case 2:
  10. name = "left"
  11. case 3:
  12. name = "right"
  13. case 4:
  14. name = "front"
  15. case 5:
  16. name = "back"
  17. }
  18. fmt.Println(name)
  19. ...
  20. }

如果值的数量达到二十个或更多,上述方法会变得相当繁琐。

似乎最简洁的方法是这样的:

  1. func foo() {
  2. ...
  3. fmt.Println(strings.Split(facenames, ",")[f])
  4. ...
  5. }
  6. const facenames = "top,bottom,left,right,front,back"

当然,我还需要检查索引是否在范围内。虽然效率目前不是问题,但我不希望过多地使用strings.Split()

是否有其他既符合惯用方式又简洁高效的方法?

英文:

Go doesn't have array constants.

My application receives messages containing several types of numeric codes which I need to display as phrases.

If array contants existed I could do something like:

<!-- language: go -->

  1. func foo() {
  2. ...
  3. fmt.Println(facename[f])
  4. ...
  5. }
  6. const facename [...]string = &quot;top&quot;, &quot;bottom&quot;, &quot;left&quot;, &quot;right&quot;, &quot;front&quot;, &quot;back&quot;

But of course there's no way to do this. The first way around this that occurs to me, and maybe a reasonable efficient one is to use a switch

<!-- language: go -->

  1. func foo() {
  2. ...
  3. name := &quot;unknown&quot;
  4. switch f {
  5. case 0:
  6. name = &quot;top&quot;
  7. case 1:
  8. name = &quot;bottom&quot;
  9. case 2:
  10. name = &quot;left&quot;
  11. case 3:
  12. name = &quot;right&quot;
  13. case 4:
  14. name = &quot;front&quot;
  15. case 5:
  16. name = &quot;back&quot;
  17. }
  18. fmt.Println(name)
  19. ...
  20. }

The above is rather tedious if the number of values gets to be twenty or more.

It seems the most concise way is something like

<!-- language: go -->

  1. func foo() {
  2. ...
  3. fmt.Println(strings.Split(facenames,&quot;,&quot;)[f])
  4. ...
  5. }
  6. const facenames = &quot;top,bottom,left,right,front,back&quot;

I will also have to check that the index is in range of course.
Although efficiency isn't a concern at the moment, it bugs me that
I'm using strings.Split() more than I want to.

Is there another way that is either idiomatic or both concise and efficient?

答案1

得分: 2

惯用的方法是使用包级别的变量:

  1. var facename = []string{"top", "bottom", "left", "right", "front", "back"}
  2. func foo() {
  3. // ...
  4. fmt.Println(facename[f])
  5. // ...
  6. }

在这种情况下,使用切片而不是数组也是惯用的做法。

英文:

The idiomatic approach is to use a package level variable:

  1. var facename = []string{&quot;top&quot;, &quot;bottom&quot;, &quot;left&quot;, &quot;right&quot;, &quot;front&quot;, &quot;back&quot;}
  2. func foo() {
  3. // ...
  4. fmt.Println(facename[f])
  5. // ...
  6. }

It's also idiomatic to use a slice instead of an array in this situation.

答案2

得分: 0

可能并不是一个很好的匹配,但是你的用例似乎基本上是一个具有字符串等效项的枚举。对于这种情况,我通常会采取以下方式:

  1. type Face uint8
  2. const (
  3. FaceTop Face = iota
  4. FaceBottom
  5. FaceLeft
  6. FaceRight
  7. FaceFront
  8. FaceBack
  9. )
  10. func (f Face) String() string {
  11. switch f {
  12. case FaceTop: return "top"
  13. case FaceBottom: return "bottom"
  14. case FaceLeft: return "left"
  15. case FaceRight: return "right"
  16. case FaceFront: return "front"
  17. case FaceBack: return "back"
  18. default: return "" // 或者添加一个错误返回,或者在枚举中添加一个零值
  19. }
  20. }
  21. func ParseFace(in string) (Face, error) {
  22. switch in {
  23. case "top": return FaceTop, nil
  24. case "bottom": return FaceBottom, nil
  25. case "left": return FaceLeft, nil
  26. case "right": return FaceRight, nil
  27. case "front": return FaceFront, nil
  28. case "back": return FaceBack, nil
  29. default: return "", errors.New("无效的面名称" + in)
  30. }
  31. }

以上是一个示例代码,用于将枚举类型与字符串等效项进行转换。

英文:

It may not be a good fit, but it appears your use case is basically an enum with string equivalents. For this I usually do something along the lines of:

  1. type Face uint8
  2. const (
  3. FaceTop Face = iota
  4. FaceBottom
  5. FaceLeft
  6. FaceRight
  7. FaceFront
  8. FaceBack
  9. )
  10. func (f Face) String() string {
  11. switch f {
  12. case FaceTop: return &quot;top&quot;
  13. case FaceBottom: return &quot;bottom&quot;
  14. case FaceLeft: return &quot;left&quot;
  15. case FaceRight: return &quot;right&quot;
  16. case FaceFront: return &quot;front&quot;
  17. case FaceBack: return &quot;back&quot;
  18. default: return &quot;&quot; // Or add an error return, or add a zero value to the enum
  19. }
  20. }
  21. func ParseFace(in string) (Face,error) {
  22. switch in {
  23. case &quot;top&quot;: return FaceTop,nil
  24. case &quot;bottom&quot;: return FaceBottom,nil
  25. case &quot;left&quot;: return FaceLeft,nil
  26. case &quot;right&quot;: return FaceRight,nil
  27. case &quot;front&quot;: return FaceFront,nil
  28. case &quot;back&quot;: return FaceBack,nil
  29. default: return &quot;&quot;,errors.New(&quot;invalid face name&quot;+in)
  30. }
  31. }

huangapple
  • 本文由 发表于 2017年6月6日 02:44:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/44375648.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定