Safely getting a subsection of a slice in Go

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

Safely getting a subsection of a slice in Go

问题

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

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

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

subsectionError := test[:10]

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

length := 10
if len(test) < length {
    length = len(test)
}
safeSubsection := test[:length]

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

英文:

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

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

But if you try something like

subsectionError := test[:10]

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

length := 10
if len(test) &lt; length {
	length = len(test)
}
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函数:

package main

import "fmt"

func min(x, y int) int {
    if y < x {
        return y
    }
    return x
}

func main() {
    test := []int{0, 1, 2, 3, 4}
    fmt.Println(test)
    sub := test[:min(10, len(test))]
    fmt.Println(sub)
}

输出结果:

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

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

package main

import &quot;fmt&quot;

func min(x, y int) int {
	if y &lt; x {
		return y
	}
	return x
}

func main() {
	test := []int{0, 1, 2, 3, 4}
	fmt.Println(test)
	sub := test[:min(10, len(test))]
	fmt.Println(sub)
}

Output:

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

答案2

得分: 1

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

package main

import (
	"fmt"
)

type Ints []int

func (i Ints) Head(count int) Ints {
	if count > len(i) {
		count = len(i)
	}
	return i[:count]
}


func main() {

	test := Ints{0, 1, 2, 3, 4}
	fmt.Printf("First 2 %v\n", test.Head(2))
	fmt.Printf("First 10 %v\n", test.Head(10))
}

如果你只需要这样做一次,可能不值得费力;但如果有几个循环在同一个列表上操作,那么这样做可能是值得的。当然,在这方面,如果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.

package main

import (
	&quot;fmt&quot;
)

type Ints []int

func (i Ints) Head(count int) Ints {
	if count &gt; len(i) {
		count = len(i)
	}
	return i[:count]
}


func main() {

	test := Ints{0, 1, 2, 3, 4}
	fmt.Printf(&quot;First 2 %v\n&quot;, test.Head(2))
	fmt.Printf(&quot;First 10 %v\n&quot;, test.Head(10))
}

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:

确定