值赋值是指将一个变量的值复制给另一个变量。当进行值赋值时,会创建原始值的一个副本,并将副本赋值给目标变量。这意味着目标变量和源变量是完全独立的,它们引用的是不同的内存地址。修改目标变量的值不会影响源变量的值。
var a = 10
var b = a // 值赋值
b = 20
fmt.Println(a) // 输出: 10
fmt.Println(b) // 输出: 20
在上述代码中,将变量 a
的值赋值给变量 b
,然后修改 b
的值不会影响到 a
。
引用赋值是指将一个引用(指针、切片、映射、通道等)复制给另一个变量。当进行引用赋值时,目标变量和源变量引用的是相同的底层数据。它们指向同一块内存地址。因此,修改目标变量会影响源变量,因为它们共享相同的数据。
var slice1 = []int{1, 2, 3}
var slice2 = slice1 // 引用赋值
slice2[1] = 10
fmt.Println(slice1) // 输出: [1 10 3]
fmt.Println(slice2) // 输出: [1 10 3]
在上述代码中,将切片 slice1
的引用赋值给 slice2
,然后修改 slice2
中的元素会影响到 slice1
,因为它们引用的是同一块内存。
需要注意的是,值赋值和引用赋值的行为取决于变量的类型。对于基本类型(如整数、浮点数、布尔值等),进行值赋值时会复制值;对于引用类型(如切片、映射、通道等),进行引用赋值时会共享底层数据。
结构体的值赋值
在 Go 语言中,结构体类型的赋值操作是进行值拷贝
package main
import "fmt"
type Person struct {
Name string
Age int
}
func main() {
p1 := Person{Name: "Alice", Age: 30}
p2 := p1
p3 := Person{Name: p1.Name, Age: p1.Age}
p1.Age = 31
fmt.Println(p2) // 输出: {Alice 30}
fmt.Println(p3) // 输出: {Alice 30}
}
在执行 p2 := p1 时,会创建一个新的结构体变量 p2,并将 p1 的字段值逐个复制到 p2 中。
创建了一个新的结构体变量 p3,并将 p1 的字段值逐个复制给 p3。因此,p3 是一个独立的结构体变量,它和 p1 指向不同的内存空间。当对 p1 的字段进行修改时,p3 不会受到影响,因为它们引用的是不同的内存地址。
结构体的引用赋值
结构体的引用赋值是指将一个结构体变量的引用(指针)赋值给另一个结构体变量。通过引用赋值,两个结构体变量将引用相同的底层数据。
引用赋值适用于结构体类型,包括自定义的结构体类型和内置的结构体类型(如切片、映射等)。
type Person struct {
Name string
Age int
}
func main() {
p1 := Person{Name: "Alice", Age: 30}
// 引用赋值
p2 := &p1
p1.Age = 31
fmt.Println(p1) // 输出: {Alice 31}
fmt.Println(*p2) // 输出: {Alice 31}
}
在上述代码中,通过 p2 := &p1 将 p1 的指针赋值给了 p2,实现了引用赋值。p2 和 p1 都指向相同的结构体数据。
因此,当修改 p1 的字段值时,通过 p2 访问也会反映出修改的结果。这是因为 p2 和 p1 引用了同一块内存空间,它们共享相同的数据。
需要注意的是,引用赋值是一种浅拷贝操作。这意味着只有结构体本身被复制,而结构体内部的引用类型字段(如切片、映射等)不会被复制。修改引用类型字段时,会影响到所有引用该字段的结构体变量。
type Person struct {
Name string
Friends []string
}
func main() {
p1 := Person{Name: "Alice", Friends: []string{"Bob", "Charlie"}}
// 引用赋值
p2 := &p1
p1.Friends[0] = "David"
fmt.Println(p1) // 输出: {Alice [David Charlie]}
fmt.Println(*p2) // 输出: {Alice [David Charlie]}
}
在上述代码中,通过引用赋值将 p1 的指针赋值给了 p2。修改 p1 的 Friends 字段的元素时,通过 p2 访问也会反映出修改的结果。这是因为 p1 和 p2 共享同一个切片的引用,它们指向相同的底层数据。
切片的值赋值
copy 是一个内置函数,用于将一个切片的元素复制到另一个切片中
package main
import "fmt"
func main() {
ls := []int{2, 45, 4, 57}
var lk = make([]int, 5)
copy(lk, ls)
lk[1] = 2222
fmt.Println(ls, lk)
}
通过 copy 函数将 ls 的元素复制到 lk,并修改了 lk[1] 的值,这个修改只会影响到 lk 自身,不会影响 ls。因为 copy 函数会将源切片的元素值复制到目标切片中。在这个过程中,源切片和目标切片是完全独立的,它们分别引用不同的底层数组。修改目标切片 lk 中的元素值不会影响原始切片 ls,因为它们引用的是不同的内存空间。