指针:pointer 数组:array 切片:slice 字典:map 结构体:struct
1.指针
- 基本概念
package main
import "fmt"
func main() {
var a int = 10
fmt.Println("内存:", a, "地址:", &a)
//输出 内存: 10 地址: 0xc00004e080
//保存某个变量的地址 需要指针类型 *int保存int的地址 **int保存*int的资质
var p *int
p = &a
fmt.Println("p:", p)
//输出
//操作的是p所指向的内存地址 也就是a
*p = 20
fmt.Println("a:", a, "p:", p)
//输出 a: 20 p: 0xc00004e080
//不能操作没有指向的指针
var b *int
*b = 30
//错误代码
}
- new关键字
package main
import "fmt"
func main() {
var p *int
//p = &a
//申请空间
p = new(int)
*p = 20
fmt.Println("*p:", p)
//输出 *p:0xc000012158
}
- 值传递的意思是我只是把值给你了,但是内存地址以及对应的值不变
- 指针传递才可操作变量
2.数组
- 声明:var a [20]int
- 自动推导类型
package main
import "fmt"
func main() {
//var id [3]int = [3]int{1, 2, 3}
id := [3]int{1, 2, 3}
fmt.Println(id)
//输出[1 2 3]
//指定下标初始化
a := [5]int{2: 10, 4: 20}
fmt.Println(a)
//输出 [0 0 10 0 20]
}
- 多维数组: a:= [3][4]{{},{},{},{}}
- 数组允许比较和赋值 == !=
- 随机数
package main
import "fmt"
import "math/rand"
import "time"
func main() {
//随机数 以时间作为种子参数
rand.Seed(time.Now().UnixNano())
for i := 0; i < 10; i++ {
//限定范围 0 - 100
fmt.Println("rand:", rand.Intn(100))
}
}
- 冒泡排序
- 挨着的两个数比较并且交换
package main
import "fmt"
import "math/rand"
import "time"
func main() {
rand.Seed(time.Now().UnixNano())
//随机数组
var a [10]int
n := len(a)
for i := 0; i < n; i++ {
a[i] = rand.Intn(100)
}
fmt.Println(a)
//冒泡排序
for i := 0; i < n-1; i++ {
for j := 0; j < n-1-i; j++ {
if a[j] > a[j+1] {
a[j], a[j+1] = a[j+1], a[j]
}
}
}
fmt.Println(a)
}
- 数组做参数传递
package main
import "fmt"
func main() {
a := [5]int{1, 2, 3, 4, 5}
Test(a)
Test01(&a)
}
//值传递
func Test(a [5]int) {
fmt.Println(a)
}
//引用传递
func Test01(p *[5]int) {
fmt.Println(*p)
}
3.slice
- 切片的概念:切片并不是数组或者数组指针,他通过内部指针和相关属性引用数组片段,以实现变长方案
- 切片的本质并不是一个动态数组,而是一个引用类型,slice总是指向一个底层array,slice的声明也可以像array一样,只是不需要长度。
- 切片内部的意义:[low:height:max]
- 长度:height - low
- 容量:max - low
- 数组和切片的区别
package main
import "fmt"
func main() {
//切片和数组的区别
//数组[]里面的长度是一个固定的常量,len和cap永远都是这个固定的常量
a := [5]int{}
fmt.Println("len:", len(a), "cap:", cap(a))
//len: 5 cap: 5
//切片[]里面为空,长度不固定
s := []int{}
fmt.Println("len:", len(s), "cap:", cap(s))
//len: 0 cap: 0
//追加
s = append(s, 10)
fmt.Println("append len:", len(s), "cap:", cap(s))
//append len: 1 cap: 1
}
- 切片的创建方式
package main
import "fmt"
func main() {
//切片的创建方式
//1.自动推导类型
s1 := []int{1, 2, 3}
//2.借助make[切片类型,长度,容量]
s2 := make([]int,5,10)
//长度和容量都为5
s3 := make([]int,5)
}
- 切片截取
- append函数:在切片末尾处增加数据
- copy(源,操作):将操作切片覆盖到源切片
- 切片函数传参为引用传递
4.map
- map是无序的
- map做函数参数为引用传递
package main
import "fmt"
func main() {
m1 := make(map[int]string)
m2 := make(map[string]string)
m3 := map[int]int{1: 1, 2: 2, 3: 3}
m1[1] = "H"
m1[2] = "e"
m1[3] = "l"
m1[4] = "l"
m1[5] = "o"
m2["i"] = "o"
fmt.Println("-------------")
fmt.Println(m1)
//map[1:H 2:e 3:l 4:l 5:o]
fmt.Println("-------------")
fmt.Println(m2)
//map[i:o]
fmt.Println("-------------")
fmt.Println(m3)
//map[1:1 2:2 3:3]
//修改
m2["i"] = "j"
fmt.Println(m2)
//map[i:j]
//遍历
for key, values := range m1 {
fmt.Println("key:", key, "values:", values)
/*
key: 5 values: o
key: 1 values: H
key: 2 values: e
key: 3 values: l
key: 4 values: l
*/
}
//判断key是否存在
values, isHave := m1[5]
fmt.Println("values", values, "isHave:", isHave)
//values o isHave: true
//删除
delete(m1, 3)
fmt.Println(m1)
//map[4:l 5:o 1:H 2:e]
}
5.结构体
package main
import "fmt"
//结构体学生
type Student struct {
id int
name string
sex bool
age int
addr string
}
func main() {
//顺序初始化,每个成员都必须初始化
var s Student = Student{1, "LGL", true, 20, "jx"}
s.age = 30
fmt.Println(s)
//{1 LGL true 20 jx}
//指定成员初始化
s1 := Student{id: 1, addr: "bj"}
fmt.Println(s1)
//{1 false 0 bj}
//指针
var s2 *Student = &Student{1, "LGL", true, 20, "jx"}
s3 := &Student{id: 1, addr: "bj"}
fmt.Println(*s2)
fmt.Println(*s3)
//new
s4 := new(Student)·
s4.id = 1
//结构体的比较
//直接 = !=
//参数传递
//和变量传递一样,值传递和引用传递
}
6.可见性
- 要让某个符号被其他package访问,需要定义大写开头
- 在结构体中也是一样的,如果其他package调用结构体中的参数则需要大写开头