---
# System prepended metadata

title: GO值类型与引用类型
tags: [Golang]

---

# GO值类型与引用类型
---

## 值类型
```javascript=
值类型包括基本数据类型，int, float, bool, string, 以及数组（arr）和结构体(struct)。

值类型变量声明后，不管是否已经赋值，编译器为其分配内存，此时该值存储于栈上。

值类型的默认值：
var i int   // int类型默认值为 0
var str string    // string类型默认值为 nil空
var b bool      // bool类型默认值为false
var arr [2]int    // 数组默认值为[0 0]
fmt.Println(&arr) // 默认已经分配内存地址，可以使用&来取内存地址
```

- **当使用等号=将一个变量的值赋给另一个变量时，如j = i ,实际上是在内存中将i的值进行了拷贝，可以通过&i 获取变量i的内存地址。此时如果修改某个变量的值，不会影响另一个。**

```go=
package main

import (
	"fmt"
)

func main() {
	//变量的赋值
	var i = 10
	j := i
	j = 101
	fmt.Println("i的值是", i, ",i的内存地址是", &i)
	fmt.Println("j的值是", j, ",j的内存地址是", &j)

	//数组的赋值
	var arr = [3]int{1, 2, 3}
	a := arr
	a[1] = 100 // 数组arr与数组a的内存地址是不一致的，所以修改数组arr的值，不会影响a数组的值
	fmt.Printf("arr的值是 %v, arr的内存地址是 %p\n", arr, &arr)
	fmt.Printf("a的值是 %v, a的内存地址是 %p\n", a, &a)
}
```
- 结果输出
```go=
i的值是 10 ,i的内存地址是 0xc000064080
j的值是 101 ,j的内存地址是 0xc000064088
arr的值是 [1 2 3], arr的内存地址是 0xc000062140
a的值是 [1 100 3], a的内存地址是 0xc000062160
```
## 引用类型
```go=
引用类型包括 pointer，slice，map ，chan，interface。

变量直接存放的就是一个内存地址值，这个地址值指向的空间存的才是值。所以修改其中一个，另外一个也会修改（同一个内存地址）。

引用类型必须申请内存才可以使用，make()是给引用类型申请内存空间。

package main

import (
	"fmt"
)

func main() {
	var arr = []int{1, 2, 3, 4, 5}
	b := arr            //此时arr，b都指向了内存中的[1 2 3 4 5]的地址
	b[1] = 10           //相当于修改同一个内存地址，所以a的值也会改变
	c := make([]int, 5) //切片的初始化
	copy(c, arr)        //将切片a copy到c
	c[1] = 20           //copy是值类型，所以a不会改变
	fmt.Printf("arr的值是 %v，arr的内存地址是 %p\n", arr, &arr)
	fmt.Printf("b的值是 %v，b的内存地址是 %p\n", b, &b)
	fmt.Printf("c的值是 %v，c的内存地址是 %p\n", c, &c)
	d := &arr //将a的内存地址赋值给d，取值用*d
	arr[1] = 11
	fmt.Printf("d的值是 %v，d的内存地址是 %p\n", *d, d)
	fmt.Printf("arr的值是 %v，arr的内存地址是 %p\n", arr, &arr)
}

// 结果输出

arr的值是 [1 10 3 4 5]，arr的内存地址是 0xc000004460
b的值是 [1 10 3 4 5]，b的内存地址是 0xc000004480
c的值是 [1 20 3 4 5]，c的内存地址是 0xc0000044a0
d的值是 [1 11 3 4 5]，d的内存地址是 0xc000004460
arr的值是 [1 11 3 4 5]，arr的内存地址是 0xc000004460

arr,b,c底层数组是一样的，但是上层切片不同，所以内存地址不一样。
```

###### tags: `Golang`