go-值赋值和引用赋值

值赋值(Value Assignment)

值赋值是指将一个变量的值复制给另一个变量。当进行值赋值时,会创建原始值的一个副本,并将副本赋值给目标变量。这意味着目标变量和源变量是完全独立的,它们引用的是不同的内存地址。修改目标变量的值不会影响源变量的值。

var a = 10
var b = a // 值赋值
b = 20
fmt.Println(a) // 输出: 10
fmt.Println(b) // 输出: 20

在上述代码中,将变量 a 的值赋值给变量 b,然后修改 b 的值不会影响到 a

引用赋值(Reference Assignment)

引用赋值是指将一个引用(指针、切片、映射、通道等)复制给另一个变量。当进行引用赋值时,目标变量和源变量引用的是相同的底层数据。它们指向同一块内存地址。因此,修改目标变量会影响源变量,因为它们共享相同的数据。

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,因为它们引用的是不同的内存空间。

你可能感兴趣的:(go,golang,算法)