指针

区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。

要搞明白Go语言中的指针需要先知道3个概念:指针地址、指针类型和指针取值。

Go语言中的指针不能进行偏移和运算,因此Go语言中的指针操作非常简单,我们只需要记住两个符号:&(取地址)和*(根据地址取值)。

ptr := &v    // v的类型为T

v:代表被取地址的变量,类型为T
ptr:用于接收地址的变量,ptr的类型就为*T,称做T的指针类型。*代表指针。

func main() {
   
	a := 10
	b := &a
	fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
	fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
	fmt.Println(&b)                    // 0xc00000e018
}


指针变量的值是指针地址。

// 指针传值
func modify1(x int) {
   
	x = 100
}

func modify2(x *int) {
   
	*x = 100
}

func main() {
   
	a := 10
	modify1(a)
	fmt.Println(a) // 10
	modify2(&a)
	fmt.Println(a) // 100
}

new和make

func main() {
   
	var a *int
	*a = 100
	fmt.Println(*a)
}

执行上面的代码会引发panic,为什么呢? 在Go语言中对于引用类型的变量,我们在使用的时候不仅要声明它,还要为它分配内存空间,否则我们的值就没办法存储。Go语言中new和make是内建的两个函数,主要用来分配内存。

new函数不太常用,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。举个例子:

func main() {
   
	a := new(int)
	b := new(bool)
	fmt.Printf("%T\n", a) // *int
	fmt.Printf("%T\n", b) // *bool
	fmt.Println(*a)       // 0
	fmt.Println(*b)       // false
}	
func main() {
   
	var a *int
	a = new(int)
	*a = 10
	fmt.Println(*a)
}

make也是用于内存分配的,区别于new,它只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

func main() {
   
	var b map[string]int
	b = make(map[string]int, 10)
	b["hello"] = 100
	fmt.Println(b)
}

map

map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。

// 定义语法
map[KeyType]ValueType

// 内存分配
make(map[KeyType]ValueType, [cap])

其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。
func main() {
   
	scoreMap := make(map[string]int, 8)
	scoreMap["张三"] = 90
	scoreMap["小明"] = 100
	fmt.Println(scoreMap)
	fmt.Println(scoreMap["小明"])
	fmt.Printf("type of a:%T\n", scoreMap)
}

// 输出
map[小明:100 张三:90]
100
type of a:map[string]int

map也支持在声明的时候填充元素,例如:

func main() {
   
	userInfo := map[string]string{
   
		"username": "mike"