指针
指针的定义和使用
希望结构体传值时,我在函数中修改的值能反应到变量中
- 定义
`go
package main
import (
“fmt”
)
type Person struct {
name string
}
func change(p *Person) {
p.name = “imo”
}
func main() {
p := Person{
name: “young”,
}
fmt.Println(p)
change(&p)
fmt.Println(p)
var pi *Person = &p
fmt.Println(pi, &p)
fmt.Printf("%p,%p", pi, &p) //打印出指针变量的地址
fmt.Println()
po := &Person{ //初始化
name: "young2",
}
fmt.Println(po)}
//输出
{young}
{imo}
&{imo} &{imo}
0xc00005c270,0xc00005c270
&{young2}
* 赋值
```go
type Person struct {
name string
}
func main() {
po := &Person{ //初始化
name: "young2",
}
fmt.Println(po)
(*po).name = "young3" //第一种赋值方式
fmt.Println(po)
po.name = "young4" //也可以当普通赋值方式 go内部优化
fmt.Println(po)
}
//输出
C:\Users\Administrator\AppData\Local\Temp\GoLand\___10go_build_main_go.exe
&{young2}
&{young3}
&{young4}
指针与其他语言不同点,go是赋值不一样。还有个点是go限制了指针的运算,一般不参与运算。相当于阉割版,但是如果确实需要运算,可以用unsafe包。。因为指针运算过于灵活,新手开发较为容易出错。。所以需要用得调用unsafe包
指针的初始化
定义结构体不初始化会给默认值,但如果指针则不行,会抛出:
”无效的内存地址或无指针取消引用“的错误。
var p Person
fmt.Println(p.name)
结构体这样输出为空
var p *Person
fmt.Println(p.name)
指针的输出为这个错误
panic: runtime error: invalid memory address or nil pointer dereference
- 初始化方式
package main
import "fmt"
type Person struct {
name string
}
func main() {
p := &Person{} //第一种初始化
var emptyP Person
p2 := &emptyP //第二种,结构体不用初始化(默认结构体已经初始化了),然后用指针指向它
var p3 *Person = new(Person) //第三种 new 相当于new了个空的结构体(类似于第二种,简化,go的优化)
fmt.Println(p.name, p2.name, p3.name)
// map channel slice初始化推荐make方法
//指针初始化推荐使用new函数,指针要初始化否则会出现nil pointer的的情况
//map 需要初始化
}
通过swap交换指针的值
正常逻辑这样能实现交换值
func main() {
a, b := 1, 2
fmt.Println(a, b)
a, b = b, a
fmt.Println(a, b)
}
//输出
1 2
2 1
但是指针不能这么改,例如下面 ,由于指针值传递。下面仅仅是针对把a的地址变成b的地址,b的地址变成a的地址,但值没变(a 地址 0x01 值 1),(b 地址 0x02 值 2),变成 (a 地址 0x02 值 1),(b 地址 0x01 值 2)
func swap(a, b *int) {
a, b = b, a
}
func main() {
a, b := 1, 2
fmt.Println(a, b)
swap(&a, &b)
fmt.Println(a, b)
}
//输出
1 2
1 2
- 那么如何来改变呢?
func swap(a, b *int) {
tmp := *a //取a地址的值,不能取变量,临时变量存储a地址的值
*a = *b //将a地址的值改为b地址的值
*b = tmp //将b地址的值改为a地址的值(由于a地址改了,所以得取tmp的)
}
func main() {
a, b := 1, 2
fmt.Println(a, b)
swap(&a, &b)
fmt.Println(a, b)
}
//输出
1 2
2 1
错误示例
func swap(a, b *int) {
*a = *b //将a地址的值改为b地址的值
*b = *a //将b地址的值改为a地址的值(由于a地址改了,所以得取tmp的)
}
func main() {
a, b := 1, 2
fmt.Println(a, b)
swap(&a, &b)
fmt.Println(a, b)
}
//输出 由于a地址的值变成b地址的值,所以b地址去取a地址的值时取得也是a地址的值。有点绕
1 2
2 2
nil在go中的细节
不同类型的数据 零值时不一样的
bool false
number 0
string “”
pointer nil
slice nil
map nil
channel、interface、function nil
struct 默认值不是nil、是具体字段的默认值。
判断时容易进入到非nil 例如
如图这个代码输出的是empty,而非nil
map类型这类最好用map去初始化