最近学习了一下 Go 语言,发现里面很多东西都和其他语言都不太一样。下面是学习过程中对 Go 中的指针部分做的一些片段性的笔记。
package main
import "fmt"
func main() {
// 一个 [3]int 型数组
arr := [...]int{1, 2, 3}
p := &arr // 一个指向 [3]int 型数组的指针
test(p) // 传递过去的是 arr 的引用
fmt.Println(arr) // [1 233 3]
}
func test(p *[3]int) {
fmt.Println(p[0]) // 1
p[1] = 233
}
Go 里面的切片是长度可变的数组,但更准确来说是指向数组这一原始类型的指针变量,所以切片是个引用值。当用户数据大于其所指向的区块范围时,这时会分配并指向到一片新的内存区域。
package main
import "fmt"
func main() {
// 值传递
arr := [...]int{1, 2, 3}
fmt.Printf("%p ---> ", &arr)
test1(arr)
// 引用传递
sli := arr[:]
fmt.Printf("%p ---> ", sli)
test2(sli)
// Result:
// 0xc4200161c0 ---> 0xc420016200
// 0xc4200161c0 ---> 0xc4200161c0
}
func test1(a [3]int) {
fmt.Printf("%p\n", &a)
}
func test2(s []int) {
fmt.Printf("%p\n", s)
}
arr1 := [3]int{1, 2, 3}
是创建了个叫 arr1 的 [3]int 型数组,
arr2 := new([3]int)
是分配了个 [3]int 型的内存空间并将 arr2 指向了它,等同于 arr2 := &[3]int{}
package main
import "fmt"
func main() {
arr1 := [3]int{1, 2, 3}
arr2 := new([3]int)
fmt.Println(arr1, arr2) // [1 2 3] &[0 0 0]
test1(&arr1)
test2(arr2) // 使用 new 创建的变量本身就是一个指针,不需要加 & 符号
fmt.Println(arr1, arr2) // [233 2 3] &[233 0 0]
}
func test1(a *[3]int) {
a[0] = 233
}
func test2(a *[3]int) {
a[0] = 233
}
package main
import "fmt"
func main() {
test2()
}
func test1() {
arr := [...]int{1, 2, 3}
sli := arr[:]
fmt.Printf("%p ---> %p\n", &arr, sli)
// 0xc4200161c0 ---> 0xc4200161c0
// 证实:切片是指向数组的指针
}
func test2() {
arr := [...]int{1, 2, 3}
sli1 := arr[:]
fmt.Println(sli1)
sli2 := new([]int)
*sli2 = arr[:]
fmt.Println(*sli2)
fmt.Printf("%p ---> %p ---> %p\n", &arr, sli1, sli2)
// 0xc4200161c0 ---> 0xc4200161c0 ---> 0xc42000a080
// 证实:sli2 得到了新分配的内存空间
}