提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
Golang中除了int之类的基础数据类型,还有指针,结构体和数组之类的复合数据类型。
本篇文章来学习一下Golang的复合数据类型
提示:以下是本篇文章正文内容,下面案例可供参考
一、Pointer
和C一样,Golang也有指针,用法和C也相似
如:
var p *int //p为指向int类型的地址值
i := 8
p = &i //&是取地址符号
fmt.Println(*p) //输出8
fmt.Println(*p) //输出地址,像0x12938920f2
p += 1 //在golang中,是不允许对指针进行运算操作的,会出现 invalid operation: p + 1 (mismatched types *int and int),这和C是不一样的
二、Struct
结构体是一个数据的结合体,如:
type Vertex struct {
X int
Y int
}
访问格式:
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2} //v是Vertex类型
t := Vertex{X:1, Y:2} //可以使用名字来对应赋值
p := &v //p是*Vertex类型
p.X = 1e9 //注意: 在golang中这么访问是没问题的
(*p).X = 1000 //注意: 这么访问也是没问题的
//关于上面两行代码,A tour of Go的解释是(*p).X这样写是很麻烦的,go允许我们用p.X代替,并不需要显式的解引用。
//有这个规则的话,我们就不能从访问成员的符号来判断变量是指针还是值了
fmt.Println(v)
}
三、Array
表达式如下:
var a [10]int //因为数组的长度是数组的一部分,所有数组不能重新分配大小
Slice
上面说数组是固定大小的,但切片是很灵活的
表达式大概是:
primes := [6]int{2, 3, 5, 7, 11, 13} //我是数组
var a []int = primes[1:4] //就像没有规定长度的数组,切片不存储任何数据,就是底层数组的一部分,形式和python的切片很像
fmt.Println(len(a)) //这个是3
fmt.Println(cap(a)) //这个是5,他会包含数组最后两个,这是切片可以扩展的内存
切片为0,代表他没有底层数组,值为nil
make
首先说明,make不是一个数据类型,它是一个函数,可以用来创建动态数组,也就是切片
用法如下:
a := make([]int, 5) // len(a)=5, 值都为0
b := make([]int, 0, 5) // len(b)=0, cap(b)=5,值为0
b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:] // len(b)=4, cap(b)=4
append
这也是个函数,用来向切片里添加元素,原型如下:
func append(s []T, vs ...T) []T //当添加的切片大于原来的底层数组,要重新分配一个底层数组
四、map
当map为空时,值为nil,map没有key,且不能添加key
make函数,会返回一个给定类型的map,同时初始化:
package main
import "fmt"
type Vertex struct {
Lat, Long float64
}
var m map[string]Vertex
func main() {
m = make(map[string]Vertex) //不用make,未被初始化,为nil,不能分配key
//m := map[string]int 正常运行
//var m map[string]int panic: assignment to entry in nil map
m["Bell Labs"] = Vertex{
40.68433, -74.39967,
}
fmt.Println(m["Bell Labs"]) //{40.68433 -74.39967}
}
五、function value
函数也是值,它可以被传递,作为参数值,或者返回值
如:
package main
import (
"fmt"
"math"
)
func compute(fn func(float64, float64) float64) float64 { //接收一个类型为func(float64, float64) float64的函数值
return fn(3, 4)
}
func main() {
hypot := func(x, y float64) float64 {
return math.Sqrt(x*x + y*y)
}
fmt.Println(hypot(5, 12))
fmt.Println(compute(hypot))
fmt.Println(compute(math.Pow))
}
闭包
go函数可能是一个闭包,闭包也是一个函数值,这个函数值引用它函数体外的变量,这个函数可以访问和分配这个引用值。这种情况下,函数被绑定到变量上
闭包示例:
package main
import "fmt"
func adder() func(int) int { //返回一个闭包
sum := 0 //sum就是上面说的函数体外的变量,这个闭包和这个sum是绑定的
return func(x int) int {
sum += x
return sum
}
}
func main() {
pos, neg := adder(), adder() //pos,neg 是两个闭包
for i := 0; i < 10; i++ {
fmt.Println(
pos(i),
neg(-2*i),
)
}
}