go基础 指针

go基础 指针,第1张

指针有很强大的功能,是C语言性能强大的基础。

// go语言中有一个list, 是数据结构中提到的链表,基于指针实现。
// python中的list还是基于数组实现的。
指针的基本概念和 *** 作

我们先通过一个程序示例了解什么是指针(保存地址的变量),指针的定义以及基本使用。

程序示例:

package main

import "fmt"

func swap(a int, b int)  {
	c := a
	a = b
	b = c
}

func main() {
	a := 0
	b := 9
	swap(a, b)
	fmt.Println(a, b)	// 没有交换a和b的值,因为值传递
	a, b = b, a
	fmt.Println(a, b)	// a和b的值进行了交换

	// 指针:对于内存而言,每个字节都有地址,可以通过16进制打印出来
	fmt.Printf("%p\n", &a)		// 打印a地址

	// 保存地址的变量
	var p1 *int
	p1 = &a		// p1会保存a的地址
	fmt.Println(p1)		// 同样会打印a地址

	// 修改或获取指针指向的变量的值
	*p1 = 5
	fmt.Println(a)
		// *p1可以获取值 // p1可以获取地址
	fmt.Printf("值为:%d; 地址为: %p", *p1, p1)


}

运行结果:

0 9
9 0
0xc00000a088
0xc00000a088
5
值为:5; 地址为: 0xc00000a088

 上面的示例了解了指针的基本概念和使用方法后,现在可以解决示例中交换不成功的问题了

程序示例:

package main

import "fmt"

func swap(a *int, b *int)  {
	c := *a
	*a = *b
	*b = c
}

func main() {
	a := 0
	b := 9
	fmt.Println("交换前a和b:", a, b)
	swap(&a, &b)
	fmt.Println("交换后a和b:", a, b)

}

运行结果:

交换前a和b: 0 9
交换后a和b: 9 0

 我们已经知道,go中的数组是值传递,当数组的数据量很大的时候,改用指针数组进行引用传递显然会节省内存。

python的list和dict中就使用的是引用传递。

指向数组的指针和指针数组

各种语言指针差异

python或Java是极力屏蔽指针的,C/ C++确提供功能强大的指针。

C/ C++中的指针功能很强大,指针的转换,指针的偏移,指针的运算均可。但是不熟悉的人可能会误用或错用指针,例如 *** 作了属于 *** 作系统运行的地址。

go语言没有屏蔽指针,但是go语言在指针上做出了很多限制,安全性高很多,但相对C/ C++灵活性会低一些。

指针 *** 作涉及到的两个符号&和*

make函数,new函数和nil

go函数中直接定义一个指针后赋值会报错,因为go语言中的指针变量申明后没有默认初始值。程序示例如下:

报错程序示例:

import "fmt"

func main() {
	var p1 *int
	*p1 = 10
	fmt.Println(*p1)
}

运行结果:

 go中有默认值的类型为int byte rune float bool string这几个基本类型。指针、切片、map、接口这些默认值是nil,意思是没有默认值。

程序示例:

package main

import "fmt"

func main() {

	var a int
	a = 10
	fmt.Println(a)

	var p1 *int
	p1 = &a
	fmt.Println(*p1)
}

运行结果:

10
10
make和new

如何给指针或者其他没有默认值的数据类型在声明时候给一个默认值开辟内存空间呢?使用make和new

new函数返回的是这个值的地址make函数返回的是指定类型的实例

程序示例:

package main

import "fmt"

func main() {
	
	//var p1 *int = make(int)	//会报错:cannot make type int
	var p1 *int = new(int)	//开辟内存空间设置值为0
	*p1 = 10
	fmt.Println(*p1)

	m2 := make(map[int] int)
	fmt.Println(m2)

	m1 := make(map[string] string)
	m1["a"] = "A"
	fmt.Println(m1)
}

运行结果:

10
map[]
map[a:A]

new函数执行过程

new是用来分配内存的内建函数,区别于其他语言中new会初始化内存,golang中的new只会将内存置零。

new 的作用是初始化一个指向类型的指针(*T),make 的作用是为 slice,map 或 chan 初始化并返回引用(T)。

nil的理解

指针、切片、map、接口这些默认值是nil,意思是没有默认值,且这个nil不是同一个地址空间的nil。

程序示例:

package main

import "fmt"

func main() {
	var m1 map[string] string
	if m1 == nil {
		fmt.Println("map声明后的默认值是nil")
	}

	var s1 [] string
	if s1 == nil {
		fmt.Println("slice声明后的默认值是nil")
	}

	var e1 error
	if e1 == nil {
		fmt.Println("error声明后的默认值是nil")
	}
}

运行结果:

map声明后的默认值是nil
slice声明后的默认值是nil
error声明后的默认值是nil

对于python来说,如果变量赋值为none,指向的是同一个None.

程序示例:

a = None
b = None
if id(a) == id(b):
    print ("a和b的None指向相同的None")
else:
    print ("a和b的None指向不同的None")

运行结果:

a和b的None指向相同的None

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/995464.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存