一、值类型
值类型的数据直接包含值,当它们被赋值给一个新的变量或者作为参数传递给函数时,实际上是创建了原值的一个副本。这意味着对新变量的修改不会影响原始变量的值。
Go中的值类型包括:
- 基础类型:int,float64,bool,string等。
- 数组([N]Type):固定大小的元素序列,所有元素必须同一类型。
- 结构体(struct): 自定义的复合类型。
测试:传入上述值类型是否能改变原始变量值
package main
import "fmt"
func modifyString(str string) {
str = "字符串222"
}
// 注意这里arr 类型为[5]int,因为数据长度是数组类型的一部分
func modifyArr(arr [5]int) {
arr[0] = 100
}
type User struct {
name string
age int
}
func modifyUser(user User) {
user.age = 20
}
func main() {
// 测试string
strstr := "字符串111"
modifyString(strstr)
fmt.Println(strstr)
//测试数组
arr := [5]int{1, 2, 3, 4, 5}
modifyArr(arr)
fmt.Println(arr)
// 测试结构体
user := User{
name: "xiaoming",
age: 18,
}
modifyUser(user)
fmt.Println(user)
}
输出:
二、引用类型
引用类型不存储值本身,而是存储一个指向实际值的地址。当你将引用类型的变量赋值给新的变量或传递给函数时,你实际上是在共享同一个底层数据。因此,通过任何持有引用的变量所做的更改都将反映在其他所有引用上。
Go中的引用类型包括:
- 切片(slice)
- 映射(map)
- 通道(channel)
- 指针(pointer)
测试:传入上述引用类型能否改变原始的值
package main
import (
"encoding/json"
"fmt"
)
func modifySlice(slice []int) {
slice[0] = 100
}
func modifyMap(customeMap map[string]string) {
customeMap["a"] = "xxx"
}
func modifyChannel(ch chan int) {
// 向channel发送数据
ch <- 42
}
func modifyPtr(ptr *int) {
*ptr = 20 // 修改指针指向的值
}
func main() {
// 测试切片
slice := []int{1, 2, 3}
modifySlice(slice)
fmt.Println(slice)
// 测试map
customeMap := map[string]string{
"a": "a",
"b": "b",
}
modifyMap(customeMap)
jsonBytes, err := json.Marshal(customeMap)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(jsonBytes))
// 测试channel
// 创建一个无缓冲的channel,用于传输int类型的数据
ch := make(chan int)
// 开启一个新的goroutine,在其中调用modifyChannel函数
go modifyChannel(ch)
// 从channel接收数据并打印
value := <-ch
fmt.Println("channel接收数据:", value)
// 测试指针
var ptr *int = new(int)
fmt.Println("ptr初始值:", *ptr)
modifyPtr(ptr)
fmt.Println("ptr修改后:", *ptr)
}
输出: