指针
Go里的指针保存了值的内存地址, *T指向的是T类型的指针, 零值为nil
var p *string
,&
操作符会生成一个指向变量的指针
a := 2
c = &a
*
操作符用来指向指针的底层值, go没有指针运算.
package main
import "fmt"
func main() {
a, b := 2, 3
c := &a // 指向a
fmt.Println(*c) //读取指针c的值 : 2
*c = 22
fmt.Println(a) //查看a的值: 22
c = &b
*c = *c + 1
fmt.Println(b) // 4
}
结构体
结构体是一组字段, 可以用点来访问字段
package main
import "fmt"
type Person struct {
name string
age int
}
func main() {
person := Person{"zhangsan", 22}
fmt.Println(person) //{zhangsan 22}
fmt.Println(person.name) //zhangsan
p1 := Person{name: "lisi"} // 可以指定某个字段,其他字段为零值
p2 := Person{}
p3 := &Person{"mazi", 33} // &返回指针
fmt.Println(p1, p2, p3) //{lisi 0} { 0} &{mazi 33}
}
数组
类型[x]T表示有x个T类型的值的数组, var arr [3]int
声明了有3个整数的数组, 数组不能改变大小.
package main
import "fmt"
func main() {
var arr [3]int
arr[0] = 1
arr[1] = 2
arr[2] = 3
fmt.Println(arr) //[1 2 3]
arr1 := [3]int{1, 2, 3}
fmt.Println(arr1) // [1 2 3]
}
切片
数组的大小是固定的,但是切片可以为数组提供动态的大小,更加常用, []T
表示元素类型为T的切片,通过2个下标来取值,比如 arr[1:3]
,包含了arr的下标1-2的元素.
package main
import "fmt"
func main() {
arr := [5]int{1, 2, 3, 4, 5}
s := arr[1:3]
fmt.Println(s) // [2 3]
s[0] = 22
fmt.Println(arr) //[1 22 3 4 5] 切片的改变会引起原数组的改变
s1 := []int{1, 2, 3} //会直接构建一个引用数组的切片
fmt.Println(s1) // [1 2 3]
fmt.Printf("the type of s1 is %T\n", s1) //the type of s1 is []int
s2 := arr[:] // 下边界默认是0, 上边界是数组的长度, 可以省略
s3 := arr[:5]
fmt.Println(s2, s3) //[1 22 3 4 5] [1 22 3 4 5]
}
切片的容量和长度
- 切片的长度是包含的元素个数.
- 切片的容量是第一个元素开始到底层数组末尾的个数.
- 长度和容量用len(s)和cap(s)获取.
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5, 6}
fmt.Println(s, len(s), cap(s)) //[1 2 3 4 5 6] 6 6
s = s[:2]
fmt.Println(s, len(s), cap(s)) //[1 2] 2 6
s = s[:4]
fmt.Println(s, len(s), cap(s)) //[1 2 3 4] 4 6
s = s[2:]
fmt.Println(s, len(s), cap(s)) //[3 4] 2 4
}
切片的零值是
nil
, 没有底层数组
make创建切片
切片可以用make函数创建. make接收的参数是t Type, size ...IntegerType
.
package main
import "fmt"
func main() {
a := make([]int, 0, 3) // 第二个参数指定长度,
fmt.Println(a, len(a), cap(a)) //[] 0 3
b := make([]int, 2)
fmt.Println(b, len(b), cap(b)) //[0 0] 2 2
c := [][]int{[]int{1, 2, 3}, []int{4, 5, 6}} // 切片里可以包含切片, 可以是任何类型
fmt.Println(c, c[1][1])
}
追加元素
使用append内建函数追加元素, 第一个参数为slice, 后面可以添加多个元素, s的底层数组太小是,会自动分配一个更大的数组.
package main
import "fmt"
func main() {
var s []int
s = append(s, 1)
fmt.Println(s, len(s), cap(s)) //[1] 1 1
s = append(s, 2, 3, 4, 5)
fmt.Println(s, len(s), cap(s)) //[1 2 3 4 5] 5 6
}
遍历
package main
import "fmt"
func main() {
s := make([]int, 5)
for i := range s {
s[i] = i
}
fmt.Println(s)
for _, v := range s { // i, v 可以用_忽略, 如果不需要某个变量
fmt.Println(v)
}
}
映射
map相当于python中的dict, 也可以用make函数初始化.
初始化
package main
import "fmt"
type Person struct {
name string
age int
}
var m map[string]Person
func main() {
m = make(map[string]Person)
m["张三"] = Person{"张三", 22}
m["bob"] = Person{"bob", 32}
fmt.Println(m["张三"])
fmt.Println(m) //map[bob:{bob 32} 张三:{张三 22}]
// 可以省略类型名
m1 := map[string]Person{
"tom": {"tom", 22},
"danny": {"danny", 32},
}
fmt.Println(m1) //map[danny:{danny 32} tom:{tom 22}]
}
修改map
元素不存在返回的是元素类型的零值,ok为false.
package main
import "fmt"
func main() {
m := make(map[string]int)
m["bob"] = 22
m["danny"] = 32
fmt.Println("bob", m["bob"])
delete(m, "bob") // 删除元素
v, ok := m["bob"]
fmt.Println(v, ok) //0 false
v, ok = m["danny"]
fmt.Println(v, ok) //32 true
}
闭包
package main
import "fmt"
// 闭包
func fib() func() int {
a, b := 0, 1
return func() int {
tmp := a
a, b = b, a+b
return tmp
}
}
func main() {
f := fib()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}