Go: deep copy slices

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

Go: deep copy slices

问题

我想读取一个表示十六进制数的字符串切片,并将它们解码为字节切片的切片([]string --> [][]byte)。这是我目前的代码:

  1. func (self *algo_t) decode_args(args []string) ([][]byte, error) {
  2. var data [][]byte
  3. for i := uint32(0); i < self.num_args; i++ {
  4. data = make([][]byte, self.num_args)
  5. tmp, err := hex.DecodeString(args[i])
  6. fmt.Printf("i = %d\ttmp = %x\n", i, tmp)
  7. data[i] = make([]byte, len(tmp))
  8. copy(data[i], tmp)
  9. if err != nil {
  10. fmt.Fprintf(os.Stderr, "Error decoding hex string %s: %s\n", args[i], err.Error())
  11. return nil, err
  12. }
  13. }
  14. fmt.Printf("line 69\tdata[0] = %x\tdata[1] = %x\tdata[2] = %x\n",data[0], data[1], data[2])
  15. return data, nil
  16. }

调用这段代码并传入 args = []string{"010203","040506","070809"} 会产生以下输出:

  1. i = 0 tmp = 010203
  2. i = 1 tmp = 040506
  3. i = 3 tmp = 070809
  4. line 69 data[0] = data[1] = data[2] = 070809

推测该函数返回 [][]byte{[]byte{}, []byte{}, []byte{0x07, 0x08, 0x09}}

我理解这是由于Go语言的指针行为导致的;在这种情况下,如何进行深拷贝是最佳实践呢?

英文:

I would like to read a slice of strings representing hexadecimal numbers, and decode them to a slice of byte slices ([]string --&gt; [][]byte). This is my code so far:

  1. func (self *algo_t) decode_args(args []string) ([][]byte, error) {
  2. var data [][]byte
  3. for i := uint32(0); i &lt; self.num_args; i++ {
  4. data = make([][]byte, self.num_args)
  5. tmp, err := hex.DecodeString(args[i])
  6. fmt.Printf(&quot;i = %d\ttmp = %x\n&quot;, i, tmp)
  7. data[i] = make([]byte, len(tmp))
  8. copy(data[i], tmp)
  9. if err != nil {
  10. fmt.Fprintf(os.Stderr, &quot;Error decoding hex string %s: %s\n&quot;, args[i], err.Error())
  11. return nil, err
  12. }
  13. }
  14. fmt.Printf(&quot;line 69\tdata[0] = %x\tdata[1] = %x\tdata[2] = %x\n&quot;,data[0], data[1], data[2])
  15. return data, nil
  16. }

calling this code and passing args = []string{&quot;010203&quot;,&quot;040506&quot;,&quot;070809&quot;} yields the following output:

  1. i = 0 tmp = 010203
  2. i = 1 tmp = 040506
  3. i = 3 tmp = 070809
  4. line 69 data[0] = data[1] = data[2] = 070809

Presumably the function returns [][]byte{[]byte{}, []byte{}, []byte{0x07, 0x08, 0x09}}.

I understand that this is because of the pointer behavior of Go; what is the best practice for doing a deep copy of this kind?

答案1

得分: 2

例如,

  1. package main
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. )
  6. // 将十六进制字符串解码为字节数组
  7. func decode(s []string) ([][]byte, error) {
  8. b := make([][]byte, len(s))
  9. for i, ss := range s {
  10. h, err := hex.DecodeString(ss)
  11. if err != nil {
  12. err = fmt.Errorf(
  13. "解码十六进制字符串 %s 出错:%s\n",
  14. ss, err.Error(),
  15. )
  16. return nil, err
  17. }
  18. b[i] = h
  19. }
  20. return b, nil
  21. }
  22. func main() {
  23. s := []string{"010203", "040506", "070809"}
  24. fmt.Println(s)
  25. b, err := decode(s)
  26. if err != nil {
  27. fmt.Println(err)
  28. } else {
  29. fmt.Println(b)
  30. }
  31. s = []string{"ABCDEF", "012345", "09AF"}
  32. fmt.Println(s)
  33. b, err = decode(s)
  34. if err != nil {
  35. fmt.Println(err)
  36. } else {
  37. fmt.Println(b)
  38. }
  39. s = []string{"01", "123XYZ"}
  40. fmt.Println(s)
  41. b, err = decode(s)
  42. if err != nil {
  43. fmt.Println(err)
  44. } else {
  45. fmt.Println(b)
  46. }
  47. }

输出结果:

  1. [010203 040506 070809]
  2. [[1 2 3] [4 5 6] [7 8 9]]
  3. [ABCDEF 012345 09AF]
  4. [[171 205 239] [1 35 69] [9 175]]
  5. [01 123XYZ]
  6. 解码十六进制字符串 123XYZ 出错:encoding/hex: invalid byte: U+0058 'X'
英文:

For example,

  1. package main
  2. import (
  3. &quot;encoding/hex&quot;
  4. &quot;fmt&quot;
  5. )
  6. // Decode hex []string to [][]byte
  7. func decode(s []string) ([][]byte, error) {
  8. b := make([][]byte, len(s))
  9. for i, ss := range s {
  10. h, err := hex.DecodeString(ss)
  11. if err != nil {
  12. err = fmt.Errorf(
  13. &quot;Error decoding hex string %s: %s\n&quot;,
  14. ss, err.Error(),
  15. )
  16. return nil, err
  17. }
  18. b[i] = h
  19. }
  20. return b, nil
  21. }
  22. func main() {
  23. s := []string{&quot;010203&quot;, &quot;040506&quot;, &quot;070809&quot;}
  24. fmt.Println(s)
  25. b, err := decode(s)
  26. if err != nil {
  27. fmt.Println(err)
  28. } else {
  29. fmt.Println(b)
  30. }
  31. s = []string{&quot;ABCDEF&quot;, &quot;012345&quot;, &quot;09AF&quot;}
  32. fmt.Println(s)
  33. b, err = decode(s)
  34. if err != nil {
  35. fmt.Println(err)
  36. } else {
  37. fmt.Println(b)
  38. }
  39. s = []string{&quot;01&quot;, &quot;123XYZ&quot;}
  40. fmt.Println(s)
  41. b, err = decode(s)
  42. if err != nil {
  43. fmt.Println(err)
  44. } else {
  45. fmt.Println(b)
  46. }
  47. }

Output:

  1. [010203 040506 070809]
  2. [[1 2 3] [4 5 6] [7 8 9]]
  3. [ABCDEF 012345 09AF]
  4. [[171 205 239] [1 35 69] [9 175]]
  5. [01 123XYZ]
  6. Error decoding hex string 123XYZ: encoding/hex: invalid byte: U+0058 &#39;X&#39;

答案2

得分: 0

有一个专门用于处理深拷贝的包:http://godoc.org/code.google.com/p/rog-go/exp/deepcopy

你可以在这里查看源代码:https://code.google.com/p/rog-go/source/browse/exp/deepcopy/deepcopy.go。它涵盖了对切片和指针的拷贝,所以应该适用于你的情况。

英文:

There is a package built specifically to handle deep copy: http://godoc.org/code.google.com/p/rog-go/exp/deepcopy

You can look at the source here: https://code.google.com/p/rog-go/source/browse/exp/deepcopy/deepcopy.go. It covers copying slices and pointers, so it should cover your case.

huangapple
  • 本文由 发表于 2014年4月24日 05:34:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/23255629.html
匿名

发表评论

匿名网友

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

确定