面试题答案
一键面试值传递和引用传递的区别
- 值传递:
- 在值传递时,函数接收的是调用者传递的实际值的副本。函数内部对这个副本的任何修改,都不会影响调用者传入的原始值。
- 这意味着函数有自己独立的内存空间来存储这个副本,对副本的操作与原始数据无关。
- 引用传递:
- 引用传递时,函数接收的是调用者传递的数据的内存地址(或类似对数据的引用)。函数内部对通过这个引用访问到的数据的修改,会直接影响调用者传入的原始数据。
- 函数和调用者共享相同的数据内存空间,操作的是同一份数据。
数据类型传递方式示例
- 值传递的数据类型:
- 基本数据类型:如
int
、float64
、bool
、string
等。
package main import "fmt" func changeValue(num int) { num = num + 10 } func main() { a := 5 changeValue(a) fmt.Println(a) // 输出 5,函数内部修改未影响原始值 }
- 数组:数组在Go语言中也是值传递。
package main import "fmt" func changeArray(arr [3]int) { arr[0] = 100 } func main() { myArr := [3]int{1, 2, 3} changeArray(myArr) fmt.Println(myArr) // 输出 [1 2 3],函数内部修改未影响原始数组 }
- 基本数据类型:如
- 类似引用传递的数据类型:
- 指针:通过传递指针,函数可以修改指针指向的数据。
package main import "fmt" func changeValueWithPointer(num *int) { *num = *num + 10 } func main() { a := 5 changeValueWithPointer(&a) fmt.Println(a) // 输出 15,函数内部通过指针修改了原始值 }
- 切片(Slice):切片虽然在语法上看起来像数组,但它的底层实现类似指针,传递切片给函数时,函数内部对切片内容的修改会影响原始切片。
package main import "fmt" func changeSlice(slc []int) { slc[0] = 100 } func main() { mySlc := []int{1, 2, 3} changeSlice(mySlc) fmt.Println(mySlc) // 输出 [100 2 3],函数内部修改影响了原始切片 }
- 映射(Map):映射也是类似引用传递,函数内部对映射的修改会影响原始映射。
package main import "fmt" func changeMap(m map[string]int) { m["key"] = 200 } func main() { myMap := map[string]int{"key": 100} changeMap(myMap) fmt.Println(myMap) // 输出 map[key:200],函数内部修改影响了原始映射 }
- 通道(Channel):通道传递给函数时,函数对通道的操作会影响原始通道,类似于引用传递。
package main import "fmt" func sendData(ch chan int) { ch <- 42 } func main() { myCh := make(chan int) go sendData(myCh) data := <-myCh fmt.Println(data) // 输出 42,函数向通道发送数据影响了原始通道 close(myCh) }