复制功能是如何工作的?

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

How does the copy function work?

问题

根据文档,copy函数的工作原理如下:

copy内置函数将源切片中的元素复制到目标切片中。(作为特殊情况,它还可以将字符串中的字节复制到字节切片中。)源和目标可以重叠。copy函数返回复制的元素数量,该数量将是srcdst长度的最小值。

func copy(dst, src []Type) int

请注意,上述代码中的Type应替换为实际的数据类型。

英文:

I don't understand how the copy function works based on the documentation:

> The copy built-in function copies elements from a source slice into a
> destination slice. (As a special case, it also will copy bytes from a
> string to a slice of bytes.) The source and destination may overlap. Copy
> returns the number of elements copied, which will be the minimum of
> len(src) and len(dst).

func copy(dst, src []Type) int

答案1

得分: 21

该规范还涵盖了内置函数append()copy()Appending to and copying slices。你应该阅读它;它非常清晰明了。

让我们分析内置函数copy()的文档以及它在简单示例中的用法。你可以在Go Playground上尝试所有示例。

函数签名:

func copy(dst, src []Type) int

copy()是一个函数。它有两个参数,一个目标切片和一个源切片,它们的元素类型相同。它返回一个int类型的数字,表示实际复制的元素数量。

> 内置函数copy()将源切片的元素复制到目标切片中。

copy()将从src切片复制元素到dst切片中。

src := []int{10, 11, 12, 13, 14}
dst := []int{0, 1, 2, 3, 4}

n := copy(dst, src)
fmt.Println("n =", n, "src =", src, "dst =", dst)

输出:

n = 5 src = [10 11 12 13 14] dst = [10 11 12 13 14]

它复制了所有五个元素,复制后目标切片与源切片具有相同的元素。

让我们继续示例:

dst = []int{0, 1}

n = copy(dst, src)
fmt.Println("n =", n, "src =", src, "dst =", dst)

输出:

n = 2 src = [10 11 12 13 14] dst = [10 11]

只有两个元素被复制,因为目标切片只有两个元素。

继续:

src = []int{10, 11}
dst = []int{0, 1, 2, 3, 4}

n = copy(dst, src)
fmt.Println("n =", n, "src =", src, "dst =", dst)

输出:

n = 2 src = [10 11] dst = [10 11 2 3 4]

再次,只有两个元素被复制,但这次是因为源切片只有两个元素。

因此,copy()将只复制源切片或目标切片中较小的元素数量。换句话说,它将复制源切片“提供”的元素数量或目标切片“容纳”的元素数量中较小的那个。

> (作为特例,它还可以将字符串的字节复制到字节切片中。)

这意味着如果目标是[]byte,源也可以是string

str := "Hello, World!"
data := make([]byte, 5)
n = copy(data, str)
fmt.Println("n =", n, "str =", str, "data =", data)
fmt.Printf("data as string: %s\n", data)

输出:

n = 5 str = Hello, World! data = [72 101 108 108 111]
data as string: Hello

这次源是一个stringcopy()复制了string的五个字节(这是Go在内存中存储字符串的方式)的UTF-8表示。

> 源和目标可能重叠。

这意味着即使目标是一个与源切片共享相同底层数组的切片,并且源和目标指定的数组部分有共同部分(重叠),copy()也能正常工作。

例如:

copy(src, src[1:])
fmt.Println("n =", n, "src =", src)

输出:

n = 4 src = [1 2 3 4 4]

这里我将src[1:]指定为源,它是去掉第一个元素的源(这是一种重新切片)。由于我排除了第一个元素,copy()的源有四个元素,因此复制了4个元素。结果是元素被“移动”到一个索引减1的位置(因此切片中的第一个元素0现在已经不存在),并且最后一个元素没有被触及(因为只复制了四个元素)。

> copy()返回复制的元素数量,该数量将是len(src)len(dst)中较小的那个。

我们在上面的示例中已经看到了这一点。

如果你想了解更多关于切片的知识:

Go切片:用法和内部原理

数组、切片(和字符串):'append'的机制

英文:

The specification also covers the builtin functions append() and copy(): Appending to and copying slices. You should read it; it's quite clear.

Let's analyze the documentation of the builtin copy() function and its uses with simple examples. You can try all the examples on the Go Playground.

Signature:

func copy(dst, src []Type) int

copy() is a function. It has two parameters, a destination and a source slice, whose element type is the same. It returns a number of type int which is the number of elements actually copied.

> The copy built-in function copies elements from a source slice into a destination slice.

copy() will copy elements from the src slice into the dst slice.

src := []int{10, 11, 12, 13, 14}
dst := []int{0, 1, 2, 3, 4}

n := copy(dst, src)
fmt.Println("n =", n, "src =", src, "dst =", dst)

Output:

n = 5 src = [10 11 12 13 14] dst = [10 11 12 13 14]

It copied all five elements, and after the copy the destination has the same elements as the source.

Let's continue the example:

dst = []int{0, 1}

n = copy(dst, src)
fmt.Println("n =", n, "src =", src, "dst =", dst)

Output:

n = 2 src = [10 11 12 13 14] dst = [10 11]

Only two elements were copied because the destination only had two elements.

Continuing:

src = []int{10, 11}
dst = []int{0, 1, 2, 3, 4}

n = copy(dst, src)
fmt.Println("n =", n, "src =", src, "dst =", dst)

Output:

n = 2 src = [10 11] dst = [10 11 2 3 4]

Again, only two elements were copied, but this time because the source had only two elements.

So copy() will only copy as many elements as the source or destination has, whichever is smaller. Or in other words, as many as the source "provides" or destination can "accommodate", whichever is smaller.

> (As a special case, it also will copy bytes from a string to a slice of bytes.)

This means that the source can also be a string if the destination is a []byte:

str := "Hello, World!"
data := make([]byte, 5)
n = copy(data, str)
fmt.Println("n =", n, "str =", str, "data =", data)
fmt.Printf("data as string: %s\n", data)

Output:

n = 5 str = Hello, World! data = [72 101 108 108 111]
data as string: Hello

This time the source was a string and copy() copied five bytes of the UTF-8 representation of the string (this is how Go stores strings in memory).

> The source and destination may overlap.

This means that copy() works correctly even if the destination is a slice which shares the same underlying array as the source slice, and the part of the array designated by source and destination has common parts (overlap).

For example:

copy(src, src[1:])
fmt.Println("n =", n, "src =", src)

Output:

n = 4 src = [1 2 3 4 4]

Here I specified src[1:] as the source, which is the source without the first element (this is a reslicing). Since I excluded the first element, the source of copy() has four elements, so 4 elements were copied. The result is that elements were "shifted" to a 1-less index (therefore the first element being 0 is now gone from the slice), and the last element was not touched (because only four elements were copied).

> Copy returns the number of elements copied, which will be the minimum of len(src) and len(dst).

We've seen this in the above examples.

If you need to learn more about slices:

Go Slices: usage and internals

Arrays, slices (and strings): The mechanics of 'append'

答案2

得分: 2

这是一个使用内置的copy函数的基本示例:

// 源切片
source := []int{1, 2, 3}

// 目标切片是要复制到的地方
destination := make([]int, len(source))

// copy函数返回从源切片复制到目标切片的元素数量
copies := copy(destination, source)

// 一些打印
fmt.Printf("复制了%d个元素\n", copies) // 输出:复制了3个元素
fmt.Println("目标切片:", destination) // 输出:目标切片:[1 2 3]

示例 Playground


如果destination切片的长度为n,而source切片的长度为m,且n < m,则目标切片将被填充为源切片的前n个元素:

source := []int{1, 2, 3}
destination := make([]int, 1) // <-- 注意这里的1
copies := copy(destination, source)
fmt.Printf("复制了%d个元素\n", copies) // 输出:复制了1个元素
fmt.Println("目标切片:", destination) // 输出:目标切片:1

示例 Playground


一个需要注意的地方是,如果你将目标切片声明为切片字面量,像这样:

destination := []int{}

长度将为0,不会复制任何元素。

英文:

Here is a basic example of how to use the built-in copy function:

// The source slice
source := []int{1, 2, 3,}

// The destination slice is where things will be copied to
destination := make([]int, len(source))

// The copy function returns a count of how many elements are
// copied from the source slice to the destination slice
copies := copy(destination, source)

// Some printing
fmt.Printf(&quot;copied %d elements\n&quot;, copies)  // Outputs: copied 3 elements
fmt.Println(&quot;destination slice:&quot;, destination) // Outputs: destination slice: [1 2 3]

Example Playground


If the destination slice is of length n, and the source slice is of length m, and n < m the destination slice will be filled with the first n elements of the source slice:

source := []int{1, 2, 3,}
destination := make([]int, 1) // &lt;-- Notice the 1
copies := copy(destination, source)
fmt.Printf(&quot;copied %d elements\n&quot;, copies)  // Outputs: copied 1 elements
fmt.Println(&quot;destination slice:&quot;, destination)  // Outputs: destination slice: [1]

Example Playground


A gotcha is that if you declare you destination slice as a slice literal like this:

destination := []int{}

The length will be 0 and nothing will be copied in.

huangapple
  • 本文由 发表于 2015年9月18日 10:30:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/32642907.html
匿名

发表评论

匿名网友

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

确定