为什么将 Golang 字节数组的对象属性赋值给另一个变量时会被清除?

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

Why Golang object property of byte array will be wiped when assigned to another variable

问题

我们需要在使用后清除一些变量。但是当它被赋值给结构体中的[]byte字段时,这似乎非常奇怪。

为什么这个[]byte的赋值不是一个拷贝,而是一个指针?

我应该怎么做才能保留结构体a.bs中的值,但清除作为局部变量的b

package main

import "fmt"

type so struct {
	bs []byte
}

func zeroes(n int) []byte {
	return make([]byte, n)
}

func wipeBytes(b []byte) {
	copy(b, zeroes(len(b)))
}


func main() {
	a := so{bs: []byte{0x01, 0x02}}
	b := a.bs
	wipeBytes(b)
	fmt.Println(b)    //b == []byte{}
	fmt.Println(a.bs) //a.bs == []byte{}
}

链接:http://play.golang.org/p/MT_wAHj2OM

英文:

We need to wipe out some variables after use. But it seems really weird when it's assigned with a []byte field in a struct.

Why this assignment of []byte is not a copy but a pointer?

What should I do to keep the value in struct a.bs, but wipe out the b as local variable?
http://play.golang.org/p/MT_wAHj2OM

package main

import "fmt"

type so struct {
	bs []byte
}

func zeroes(n int) []byte {
	return make([]byte, n)
}

func wipeBytes(b []byte) {
	copy(b, zeroes(len(b)))
}


func main() {
	a := so{bs: []byte{0x01, 0x02}}
	b := a.bs
	wipeBytes(b)
	fmt.Println(b)    //b == []byte{}
	fmt.Println(a.bs) //a.bs == []byte{}
}

答案1

得分: 1

切片本质上是引用类型。分配一个切片并不会复制其内容。你可以将切片值看作是一个“切片头”结构,其中包含指向切片底层数组的指针,以及切片在数组中的偏移量和长度。当你复制切片时,复制的是这个结构,而不是数组中的任何值。

你可以使用以下代码:

b := make([]byte, len(a.bs)))
copy(b, a.bs)

b创建为一个新的切片,并将a.bs的内容复制到其中。然后,对其中一个切片所做的任何操作都不会影响另一个切片。

英文:

Slices are inherently reference-y things. Assigning one doesn't copy its contents. You can think of a slice value as being a "slice head" structure, which contains a pointer to the slice's underlying array, and the offset and length of the slice within the array. It's this structure that's copied when you copy the slice, not any of the values in the array.

You can do

b := make([]byte, len(a.bs)))
copy(b, a.bs)

to make b a new slice and copy a.bs's contents into it. Then nothing you do to one will have any effect on the other.

答案2

得分: 1

在声明/创建array[]byte{0x01, 0x02})时,你没有指定长度([2]byte{0x01, 0x02}),这意味着它是一个切片而不是数组。切片对象在内部包含指向其内容的指针。

英文:

When declaring/creating the 'array' ([]byte{0x01, 0x02}), you're not specifying a length ([2]byte{0x01, 0x02}), which means that it's a slice instead of an array. And slices objects internally contains a pointer to it's content.

答案3

得分: 0

func ObjectAssign(target interface{}, object interface{}) {
    // 将 object 的属性值赋给 target 的属性值
    // 使用模式匹配(https://golang.org/pkg/reflect/#Value.FieldByName)
    // 参考:https://stackoverflow.com/questions/35590190/how-to-use-the-spread-operator-in-golang
    t := reflect.ValueOf(target).Elem()
    o := reflect.ValueOf(object).Elem()
    for i := 0; i < o.NumField(); i++ {
        for j := 0; j < t.NumField(); j++ {
            if t.Field(j).Name() == o.Field(i).Name() {
                t.Field(j).Set(o.Field(i))
            }
        }
    }
}
英文:
func ObjectAssign(target interface{}, object interface{}) {
    // object atributes values in target atributes values
    // using pattern matching (https://golang.org/pkg/reflect/#Value.FieldByName)
    // https://stackoverflow.com/questions/35590190/how-to-use-the-spread-operator-in-golang
    t := reflect.ValueOf(target).Elem()
    o := reflect.ValueOf(object).Elem()
    for i := 0; i &lt; o.NumField(); i++ {
        for j := 0; j &lt; t.NumField(); j++ {
            if t.Field(j).Name() == o.Field(i).Name() {
                t.Field(j).Set(o.Field(i))
            }
        }
    }
}

huangapple
  • 本文由 发表于 2015年8月6日 14:47:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/31848628.html
匿名

发表评论

匿名网友

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

确定