第四章:Go语言指针

golang-gopher.png

1. 指针类型

指针就是存储变量内存地址的变量,指针也是一种变量,我们称之为指针变量

声明一个 T 类型的指针,指针声明之后默认值都是nil

package main

import "fmt"

func main() {
    // 声明一个int类型指针
    var p *int
    // 声明一个string类型指针
    var s *string
    // 声明一个bool类型指针
    var b *bool
    // 声明一个interface类型指针
    var i *interface{}
    fmt.Printf("p default value = %v  p type = %T\n",p,p)
    fmt.Printf("s default value = %v  p type = %T\n",s,s)
    fmt.Printf("b default value = %v  p type = %T\n",b,b)
    fmt.Printf("i default value = %v  p type = %T\n",i,i)
}

p default value = <nil>  p type = *int
s default value = <nil>  p type = *string
b default value = <nil>  p type = *bool
i default value = <nil>  p type = *interface {}

指针的初始化和基本使用

package main

import "fmt"

func main() {
    // 声明一个整型变量 n 并且初始化赋值为99
    var n int = 99
    // 获取n在内存中的地址,使用 & 符号取一个变量的地址
    fmt.Println("整型变量n的地址是 :", &n)
    // 声明一个指针变量p 类型是int指针类型
    var p *int
    // 整数指针变量p初始化赋值,将整数变量n的地址赋给指针变量p
    p = &n
    // 打印p的值(保存的是n的内存地址)
    fmt.Println("指针变量p的值是   :", p)
    // 指针变量p本身也有一个内存地址
    fmt.Println("指针变量P本身的内存地址是", &p)
    // 通过 * 访问指向变量的值
    fmt.Println("指针变量p指向变量的值是 :", *p)
    // 修改指针变量p指向变量n的值
    fmt.Println("整型变量n的值是", n)
    *p = 100
    // 查看n的值被改变了
    fmt.Println("修改后整型变量n的值是", n)

}

整型变量n的地址是 : 0xc000054080
指针变量p的值是   : 0xc000054080
指针变量P本身的内存地址是 0xc000080020
指针变量p指向变量的值是 : 99
整型变量n的值是 99
修改后整型变量n的值是 100

当指针变量没有指向的时候不能进行 (*p)的操作

package main

import "fmt"

func main() {
    var p *int
    // panic: runtime error: invalid memory address or nil pointer dereference
    fmt.Println(*p)
}

也就是说指针变量要使用应该给它初始化一个内存

内置new()函数也可创建指针,new() 是一个内存分配函数,传入的参数是一个类型,且返回指向的指针

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type
package main

import (
    "fmt"
)

func main() {
    // 指针变量初始化方法1
    fmt.Println("指针变量初始化方法1")
    var p *int
    var i int
    fmt.Println(&i)
    p = &i
    fmt.Println(p)
    fmt.Println(*p)
    fmt.Println("指针变量初始化方法2")
    var p2 *int
    // 使用new()函数初始化
    p2 = new(int)
    fmt.Println(p2)
    fmt.Println(*p2)
    // 和上面类似就是写法不同
    fmt.Println("指针变量初始化方法3")
    p3 := new(int)
    fmt.Println(p3)
    fmt.Println(*p3)
    // 类型推导
    var p4 = &i
    fmt.Printf("p4 value = %v ,type = %T \n",p4,p4)
}
指针变量初始化方法1
0xc000054090
0xc000054090
0
指针变量初始化方法2
0xc000054098
0
指针变量初始化方法3
0xc0000540a0
0
p4 value = 0xc000054090 ,type = *int 

指针可以指向任何类型变量,也包括指向另一个指针

package main

import "fmt"

func main(){
    var i int = 100
    var p1 = &i
    fmt.Printf("i type is %T, value = %v, memory address = %v\n",i,i,&i)
    fmt.Printf("p type is %T, value = %v, memory address = %v\n",p1,p1,&p1)
    // 创建一个指向指针的指针变量
    var p2 = &p1
    fmt.Printf("p2 type is %T, value = %v\n",p2,p2)
    // 访问的是p1变量的值,而p1也是指针变量,它的值就是一个内存地址
    fmt.Println(*p2)
    // 等价于 *p1 最终访问的是整型变量i的值
    fmt.Println(**p2)
    fmt.Println(*(*p2))
}

i type is int, value = 100, memory address = 0xc000054080
p type is *int, value = 0xc000054080, memory address = 0xc000080018
p2 type is **int, value = 0xc000080018
0xc000054080
100
100

Go语言中类型指针不能进行偏移和运算

因为这样的语言特点,带来的优势是指针变量高效的访问, 但又不会发生指针偏移,同时垃圾回收也比较容易

package main

import "fmt"

func main() {
    var i int = 98
    var p *int = &i
    var p1 = &i
    // invalid operation: p + p1 (operator + not defined on pointer)
    var p2 = p + p1
    //invalid operation: p1 + 2 (mismatched types *int and int)
    var p3 = p1 + 2
    fmt.Println(p1)
}

指针变量可以使用关系运算符 == 比较 ,但是不能进行 > 或者 < 比较

package main

import "fmt"

func main() {
    var i1 int8 = 90
    var i2 int64 = 80
    var i3 int8 = 70
    var p1 *int8 = &i1
    var p2 *int64 = &i2
    var p3 = &i2
    var p4 = &i3
    fmt.Println(p1)
    fmt.Println(p2)
    fmt.Println(p3)
    // p2 == p3
    if p2 == p3 {
        fmt.Println("p2 == p3")
    }
    //invalid operation: p2 > p1 (mismatched types *int64 and *int8)
    if p2 > p1 {
        fmt.Println("")
    }
    // invalid operation: p1 < p4 (operator < not defined on pointer)
    if p1 < p4{
        fmt.Println("p1 < p4")
    }

}

指针可以作为参数传递

package main

import "fmt"

// 函数的形参是一个整型指针类型
func modifyVar(p *int) {
    *p += 100
}
func exchangevar(i, j *int) {
    *i, *j = *j, *i
}
func main() {
    var i int = 1
    fmt.Println(i)
    modifyVar(&i)
    fmt.Println(i)
    var x, y int = 66, 99
    // 交换前的值
    fmt.Println("x = ", x)
    fmt.Println("y = ", y)
    // 交换后的值
    exchangevar(&x, &y)
    fmt.Println("x = ", x)
    fmt.Println("y = ", y)
}

1
101
x =  66
y =  99
x =  99
y =  66

案例: 使用指针变量获取命令行输入信息

package main

import (
    "flag"
    "fmt"
)
//定义一个叫做mode的指令变量 *string类型
var mode = flag.String("mode","","process mode")
func main() {
    // 解析命令行参数,将结果写入创建的指令变量中
    flag.Parse()
    if *mode == "fast"{
        fmt.Println("fast mode execute")
    }else if *mode == "slow" {
        fmt.Println("slow mode execute")
    }else {
        fmt.Println("default mode execute")
    }
}
$ go run main.go --mode=fast
fast mode execute
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,151评论 6 523
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,465评论 3 405
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 172,429评论 0 368
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,147评论 1 301
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,149评论 6 400
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,614评论 1 315
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,965评论 3 429
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,950评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,486评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,524评论 3 347
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,640评论 1 355
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,228评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,976评论 3 340
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,407评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,552评论 1 277
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,215评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,714评论 2 366

推荐阅读更多精彩内容