Go指针?取C指针有何差别?
Go指针?与C指针有何不同?
什么是指针?
指针是一个存储另一个变量的内存地址的变量。
图中所示,变量b拥有值156,并且存储在的内存地址是0x1040a124。变量a保存b的地址,现在就a指向b。
声明指针
T是指向T类型的值的指针变量的类型。让我们写一个程序来声明一个指针。
package main
import (
"fmt"
)
func main() {
b := 255
var a int = &b
fmt.Printf("Type of a is %T
", a)
fmt.Println("address of b is", a)
}
&从操作符用来获取变量的地址。上面程序的第9行我们将b变量的地址赋值给类型为int的变量a。现在变量a就称指向了变量b。当我们打印变量a的值,变量b的地址就会打印,,上面的程序会输出,你可能获得不一样的b地址值,因为b可以被分配到内存的任何地方。
Type of a is int
address of b is 0x1040a124
指针的零值
指针的零值是nil。
package main
import (
"fmt"
)
func main() {
a := 25
var b int
if b == nil {
fmt.Println("b is", b)
b = &a
fmt.Println("b after initialization is", b)
}
}
b在上述程序中最初为nil,后来被分配给a的地址。此程序输出,
b is
b after initialisation is 0x1040a124
使用ne函数创建指针
Go提供了一个方便的函数ne,用于创建指针。ne函数以一个类型作为参数并且返回新分配传参类型的零值指针。下面的例子可以清晰地表述,
package main
import (
"fmt"
)
func main() {
size := ne(int)
fmt.Printf("Size value is %d, type is %T, address is %v
", size, size, size)
size = 85
fmt.Println("Ne size value is", size)
}
上面的程序中,第8行,使用ne函数创建了int类型的指针,并且将返回指向新分配的int类型的零值的指针。类型int的零值为0,size的类型是int,并且指向0,size就是0。执行程序会打印,
Size value is 0, type is int, address is 0x414020
Ne size value is 85
指针的取值
指针取值,就是获得指针指向的变量的值,可以使用a语句。
package main
import (
"fmt"
)
func main() {
b := 255
a := &b
fmt.Println("address of b is", a)
fmt.Println("value of b is", a)
}
在上述程序的第10行中,我们取指针a的值并打印。正如预期的那样,它打印了b的值。程序的输出为,
address of b is 0x1040a124
value of b is 255
让我们写一个使用指针修改变量b的值的程序,
package main
import (
"fmt"
)
func main() {
b := 255
a := &b
fmt.Println("address of b is", a)
fmt.Println("value of b is", a)
a++
fmt.Println("ne value of b is", b)
}
上面程序的第12行,我们将 a 指向的值递增1,这将改变 b 的值,因为 a 指向 b,b的值变成了256,执行程序会输出,
address of b is 0x1040a124
value of b is 255
ne value of b is 256
将指针传递给函数
package main
import (
"fmt"
)
func change(val int) {
val = 55
}
func main() {
a := 58
fmt.Println("value of a before function call is",a)
b := &a
change(b)
fmt.Println("value of a after function call is", a)
}
在上面的程序中,在第14行中,我们将指针变量 b 传递给函数更改,该变量保存 a 的地址。在change函数中,使用8行中的取值符来更改 a 的值。该程序输出,
value of a before function call is 58
value of a after function call is 55
从函数返回指针
函数返回局部变量的指针是完全合法的。Go 编译器足够智能,它会在堆上分配这个变量。
package main
import (
"fmt"
)
func hello() int {
i := 5
return &i
}
func main() {
d := hello()
fmt.Println("Value of d", d)
}
在上面程序的第9行中,我们从函数 hello 返回局部变量 i 的地址。此代码的行为在 C 和 C++ 等编程语言中未定义,因为一旦函数hello返回,变量 i 就会超出范围。但在Go的情况下,编译器会进行转义分析,并在地址转义本地范围时在堆上分配 i。,该程序将正常运行并打印,
Value of d 5
不要将一个数组指针作为参数传给函数,使用切片替代
假设我们要对函数内的数组进行一些修改,并且对函数内部的数组所做的更改应该对调用者可见。执行此操作的一种方法是将指向数组的指针作为函数的参数传递。
package main
import (
"fmt"
)
func modify(arr [3]int) {
(arr)[0] = 90
}
func main() {
a := [3]int{89, 90, 91}
modify(&a)
fmt.Println(a)
}
在上述程序的第13行中,我们将数组 a 的地址传递给modify函数。在modify函数的第8行中,我们将90分配给数组的第一个元素。此程序输出[90 90 91]。
a[x]是(a)[x]的简写,上面程序中的(arr)[0]可以使用arr[0]替换。我们来改写下,
package main
import (
"fmt"
)
func modify(arr [3]int) {
arr[0] = 90
}
func main() {
a := [3]int{89, 90, 91}
modify(&a)
fmt.Println(a)
}
尽管这种将指向数组的指针作为函数的参数传递给函数并对其进行修改的方法有效,但它并不是在 Go 中实现此目的的惯用方法。我们有切片可以实现同样的效果。
package main
import (
"fmt"
)
func modify(sls []int) {
sls[0] = 90
}
func main() {
a := [3]int{89, 90, 91}
modify(a[:])
fmt.Println(a)
}
在上面程序的第13行中,我们将一个切片传递给 modify 函数。切片的第一个元素在修改函数中更改为90。该程序还输出[90 90 91]。,忘记将指针传递给数组,而是使用切片而不是:)。这段代码要干净得多,并且是惯用的Go :)。
Go不支持指针算法
Go 不支持指针算法,这存在于其他语言(如 C 和 C++)中。
package main
func main() {
b := [...]int{109, 110, 111}
p := &b
p++
}
上面的程序会抛出编译错误 main.go6invalid operation: p++ (non-numeric type [3]int)。
奇闻怪事
- 黎姿老公马廷强前妻 黎姿老公马廷强前妻是谁
- 紫禁城闹鬼是真的吗 紫禁城闹鬼是怎么回事
- 80年黄河透明棺材事件 80年代黄河透明棺材始末
- 51区外星人录像是真的吗 51区外星人真的存在吗
- 姜潮麦迪娜恋爱过程 姜潮麦迪娜怎么认识的
- 根达亚文明大概离现在多久 根达亚文明距今多少
- 赤塔事件真的还是假的 赤塔事件到底怎么回事
- 百慕大三角在哪个国家 百慕大三角在哪个国家的
- 邓超出轨安以轩:邓超出轨安以轩是不是真的
- 中国十大闹鬼最凶的地方 中国十大闹鬼最凶的地
- 湘西鬼结婚事件:湘西鬼结婚事件真假
- 中国昆仑山10大灵异绝密档案 中国昆仑山10大灵异
- 李维嘉的父亲是谁 李维嘉父母是哪里人
- 朱秀华事件是不是真的 朱秀华事件的真相是什么
- 太湖冤魂:太湖冤魂事件真假
- 爪哇虎和东北虎谁厉害 爪哇虎和东北虎谁厉害一