如何将切片转换为固定大小的数组?

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

How to convert slice to fixed size array?

问题

我想将一个固定大小的数组从切片转换为:

func gen(bricks []Brick) {
    if len(bricks) == 16 {
        if check(Sculpture{bricks}) {
            var b [16]Brick = bricks[0:16];
        }
    }
}

但是这会导致以下错误:

cannot use bricks[0:16] (type []Brick) as type [16]Brick in assignment

如何将切片转换为固定大小的数组?

英文:

I want to convert a fixed size array from a slice:

func gen(bricks []Brick) {
    if len(bricks) == 16 {
	    if check(Sculpture{bricks}) {
		    var b [16]Brick = bricks[0:16];
	    }
     }
}

But this results in:

 cannot use bricks[0:16] (type []Brick) as type [16]Brick in assignment

How to convert a slice into a fixed size array?

答案1

得分: 114

编辑:从Go 1.17开始,您可以使用新的切片到数组指针转换支持。请参考https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer:

s := make([]byte, 2, 4)
s0 := (*[0]byte)(s)      // s0 != nil
s1 := (*[1]byte)(s[1:])  // &s1[0] == &s[1]
s2 := (*[2]byte)(s)      // &s2[0] == &s[0]
s4 := (*[4]byte)(s)      // 报错:len([4]byte) > len(s)

对于Go 1.16及以下版本,您需要使用copy函数:

slice := []byte("abcdefgh")

var arr [4]byte

copy(arr[:], slice[:4])

fmt.Println(arr)

正如Aedolon所指出的,您也可以直接使用:

copy(arr[:], slice)

因为copy函数总是只会复制len(src)len(dst)中较小的字节数。

英文:

Edit: as of Go 1.17+, you may be able to use new support for slice-to-array conversions, https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer:

s := make([]byte, 2, 4)
s0 := (*[0]byte)(s)      // s0 != nil
s1 := (*[1]byte)(s[1:])  // &s1[0] == &s[1]
s2 := (*[2]byte)(s)      // &s2[0] == &s[0]
s4 := (*[4]byte)(s)      // panics: len([4]byte) > len(s)

<hr>

Previous answer for Go 1.16 and below:

You need to use copy:

slice := []byte(&quot;abcdefgh&quot;)

var arr [4]byte

copy(arr[:], slice[:4])

fmt.Println(arr)

As Aedolon notes you can also just use

copy(arr[:], slice)

as copy will always only copy the minimum of len(src) and len(dst) bytes.

答案2

得分: 2

我找到了一种解决问题的方法,可以在不分配任何额外空间的情况下解决问题 - 定义一个与切片具有相同结构的新结构体,并接收 unsafe.Pointer。

type MySlice struct {
	Array unsafe.Pointer
	cap   int
	len   int
}
func main(){
	a := []byte{1, 2, 3, 4}
	fmt.Printf("a before %v, %p\n", a, &a)
	b := (*MySlice)(unsafe.Pointer(&a))
	c := (*[4]byte)(b.Array)
	fmt.Printf("c before %v, %T, %p\n", *c, *c, c)
	a[1] = 5
	fmt.Printf("c after %v, %p\n", *c, c)
	fmt.Printf("a after %v, %p\n", a, &a)
}

结果如下所示:
如何将切片转换为固定大小的数组?

英文:

I found a way to solve the problem without allocating any more space - to define a new struct with the same construction as slice and receive the unsafe.Pointer.

type MySlice struct {
	Array unsafe.Pointer
	cap   int
	len   int
}
func main(){
	a := []byte{1, 2, 3, 4}
	fmt.Printf(&quot;a before %v, %p\n&quot;, a, &amp;a)
	b := (*MySlice)(unsafe.Pointer(&amp;a))
	c := (*[4]byte)(b.Array)
	fmt.Printf(&quot;c before %v, %T, %p\n&quot;, *c, *c, c)
	a[1] = 5
	fmt.Printf(&quot;c after %v, %p\n&quot;, *c, c)
	fmt.Printf(&quot;a after %v, %p\n&quot;, a, &amp;a)
}

the result shows as follows:
如何将切片转换为固定大小的数组?

huangapple
  • 本文由 发表于 2015年5月17日 18:04:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/30285680.html
匿名

发表评论

匿名网友

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

确定