浅谈go二维数组的深复制

浅谈go二维数组的深复制

在go语言中,对于一个数组的赋值,和python一样,其实并没有开辟新空间,比如下面这行代码:

1
2
3
4
5
6
7
8
9
10
package main
import "fmt"
func main(){
source:=[]int{1,2,3,4}
dist:=[]int{}
dist=source
dist[0]=999 //对第二个数组进行修改

fmt.Println(source)
}

打印的结果,为 [999,2,3,4]。这时候如果想对第二个数组进行修改,并且不影响原数组,也就是说,想让他们两个独立,这时候就需要关键字copy

1
2
3
4
5
6
7
8
9
package main
import "fmt"
func main(){
source:=[]int{1,2,3,4}
dist:=[]int{}
copy(dist,source)
dist[0]=999 //对第二个数组进行修改
fmt.Println(source)
}

输出的结果为[1,2,3,4]。这是一维数组,很好写,也很简单。

二维数组的情况

二维数组的时候,情况变得复杂起来,比如你看下面的代码

1
2
3
4
5
6
7
8
package main
import "fmt"
func main(){
source:=[][]int{{1,2,3,4},{5,6,7,8}}
dist:=[][]int{}
copy(dist,source)
fmt.Println(dist)//直接对第二个数组进行输出
}

输出的结果:[] 为空,虽然没有报错,但是实际并没有成功,也就是说,copy只能复制一维的,那我们可以遍历二维数组,然后一个一个的进行复制,行不行?答案是:可以,但是对于写法有要求。先来一份正确的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import "fmt"
func main(){
source:=[][]int{{1,2,3,4},{5,6,7,8}}

dist:=make([][]int,len(source))

for i:= range source{
dist[i]=make([]int,len(source[i]))
copy(dist[i],source[i])
}

fmt.Println(dist)
}

上面的代码中,有两个make,都不可以省略。第一个make开辟数组的行数,(注:len(source)的值为2,因为source只有两行。)。第二个make开辟数组的空间,这个比较好理解。下面是错误的示范。

错误示范

  • 不写make可不可以?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package main
    import "fmt"
    func main(){
    source:=[][]int{{1,2,3,4},{5,6,7,8}}

    dist:=[][]int{}

    for i:= range source{
    copy(dist[i],source[i])
    }

    fmt.Println(dist)
    }

    不行。

  • 写一个make可不可以

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package main
    import "fmt"
    func main(){
    source:=[][]int{{1,2,3,4},{5,6,7,8}}

    dist:=make([][]int,len(source))

    for i:= range source{
    //第二个不写
    //dist[i]=make([]int,len(source[i]))
    copy(dist[i],source[i])
    }

    fmt.Println(dist)
    }

    编译可通过,但是dist里面为空

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package main
    import "fmt"
    func main(){
    source:=[][]int{{1,2,3,4},{5,6,7,8}}

    dist:=[][]int{}
    for i:= range source{
    dist[i]=make([]int,len(source[i]))
    copy(dist[i],source[i])
    }

    fmt.Println(dist)
    }

    编译报错,数组越界,length 0 就越界


浅谈go二维数组的深复制
http://tang895.github.io/2022/07/10/浅谈go二维数组的深复制/
作者
TangYijun
发布于
2022年7月10日
许可协议