Safely getting a subsection of a slice in Go

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

Safely getting a subsection of a slice in Go

问题

我知道在Go语言中,你可以通过以下方式获取切片的子切片:

  1. test := []int{0, 1, 2, 3, 4}
  2. subsection := test[:2]

但是,如果你尝试以下操作:

  1. subsectionError := test[:10]

你会得到一个越界错误。目前,我正在使用以下方式处理:

  1. length := 10
  2. if len(test) < length {
  3. length = len(test)
  4. }
  5. safeSubsection := test[:length]

以避免错误发生。但是,是否有更好的方法来处理这个问题呢?对我来说,这种方法似乎有点笨拙,但是Go语言通常都是一种相当明确的语言。

英文:

I know that you can get a subsection of a slice in Go via

  1. test := []int{0, 1, 2, 3, 4}
  2. subsection := test[:2]

But if you try something like

  1. subsectionError := test[:10]

You'll get an out of bounds error. Currently I'm doing something like

  1. length := 10
  2. if len(test) &lt; length {
  3. length = len(test)
  4. }
  5. safeSubsection := test[:length]

To avoid the error, but is there a nicer way of doing this? It feels pretty hacky to me, but then again Go generally seems to be a pretty explicit language.

答案1

得分: 1

在Go语言中,通常的做法是将丑陋的代码隐藏在一个函数或方法中。例如,一个min函数:

  1. package main
  2. import "fmt"
  3. func min(x, y int) int {
  4. if y < x {
  5. return y
  6. }
  7. return x
  8. }
  9. func main() {
  10. test := []int{0, 1, 2, 3, 4}
  11. fmt.Println(test)
  12. sub := test[:min(10, len(test))]
  13. fmt.Println(sub)
  14. }

输出结果:

  1. [0 1 2 3 4]
  2. [0 1 2 3 4]
英文:

In Go, the answer is often to hide ugliness in a function or method. For example, a min function,

  1. package main
  2. import &quot;fmt&quot;
  3. func min(x, y int) int {
  4. if y &lt; x {
  5. return y
  6. }
  7. return x
  8. }
  9. func main() {
  10. test := []int{0, 1, 2, 3, 4}
  11. fmt.Println(test)
  12. sub := test[:min(10, len(test))]
  13. fmt.Println(sub)
  14. }

Output:

  1. [0 1 2 3 4]
  2. [0 1 2 3 4]

答案2

得分: 1

如果你经常这样做,并且觉得代码很丑陋,你可以创建一个切片类型,并在其上添加一些便利方法。如果你有很多在列表上操作的便利方法(比如min、max、head、contains等),这将非常有用。我使用这种方法在字符串或整数切片上添加contains方法。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type Ints []int
  6. func (i Ints) Head(count int) Ints {
  7. if count > len(i) {
  8. count = len(i)
  9. }
  10. return i[:count]
  11. }
  12. func main() {
  13. test := Ints{0, 1, 2, 3, 4}
  14. fmt.Printf("First 2 %v\n", test.Head(2))
  15. fmt.Printf("First 10 %v\n", test.Head(10))
  16. }

如果你只需要这样做一次,可能不值得费力;但如果有几个循环在同一个列表上操作,那么这样做可能是值得的。当然,在这方面,如果Go语言有更复杂的通用容器会更好。

英文:

If you find yourself doing this often, and the ugliness annoys you, you can make a slice type instead and put some convenience methods on this. This is useful if you have a lot of convenience methods that operate on a list (say min, max, head, contains etc). I use this to add contains to string or int slices.

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. )
  5. type Ints []int
  6. func (i Ints) Head(count int) Ints {
  7. if count &gt; len(i) {
  8. count = len(i)
  9. }
  10. return i[:count]
  11. }
  12. func main() {
  13. test := Ints{0, 1, 2, 3, 4}
  14. fmt.Printf(&quot;First 2 %v\n&quot;, test.Head(2))
  15. fmt.Printf(&quot;First 10 %v\n&quot;, test.Head(10))
  16. }

https://play.golang.org/p/OkCjHdlj0u

If you're only doing it once, it's probably not worth the effort, if you have a few loops operating on the same list, it might be. And of course this is one area where it'd be nice to have more sophisticated generic containers in Go.

huangapple
  • 本文由 发表于 2017年8月10日 21:07:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/45614597.html
匿名

发表评论

匿名网友

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

确定