指针类型
package main
func main() {
/*
//(1) 获取地址: &变量
var x = 10 // x 为整型变量
fmt.Printf("赋值前x的对应地址:%p\n", &x)
x = 100
fmt.Printf("赋值后x的对应地址:%p\n", &x)
//(2) 地址赋值:引出了指针类型 *int *string *bool *float
var p *int //p 是一个整形指针类型
p = &x // var p = &x
fmt.Printf("p的对应地址:%p\n", p)
// (3) 取值操作: 使用 *指针变量 将具体存放的值取出/修改
fmt.Printf("取值:%d\n", *p)
fmt.Println(reflect.TypeOf(*p))
*p = 10
fmt.Printf("取值:%d\n", *p)
fmt.Println(x)
*/
/*
//思考
// 值拷贝
//var a = 1
//var b = a
//b = 100
//fmt.Printf("a的值为:%d\ta的地址为:%#v\n", a, &a)
//fmt.Printf("b的值为:%d\tb的地址为:%#v\n", b, &b)
// 地址赋值
var a = 1
var b = &a // b获取到a的指针地址,便于后续*b获取/修改a指针内存储的值
var c = b // 同理,c存储和b一样的a的指针地址
*b = 100
fmt.Printf("a的值为:%d\ta的地址为:%#v\n", a, &a)
fmt.Printf("b的值为:%d\tb的地址为:%#v\n", *b, &b)
fmt.Printf("c的值为:%d\tc的地址为:%#v\n", *c, &c)
*/
/*
// 指针应用 1
var x = 100
var y = x // 值拷贝 y = x = 100
var z = &x // z存放x的指针地址
x = 20 // x = 20 = *z; y = 100
fmt.Println(x) // 20
fmt.Println(y) // 100
fmt.Println(*z) // 20
*z = 30
fmt.Println(x) // 30
*/
/*
// 指针应用 2
var x = 10
var y = &x // y取值为x的指针地址,y是一个指针变量,属于*int
var z = *y // z取值为y的指针地址,z是一个整形,属于int
x = 20
fmt.Println(x) // 20
fmt.Println(*y) // 20
fmt.Println(z) // 10
*/
/*
// 指针应用 3
var a = 100
var b = &a // b取a的指针地址,*int类型
var c = &b // c取b的指针地址,**int类型
**c = 200
fmt.Println(a) // 200
*/
/*
// 指针应用 4
p1 := 1 // p1 = 1,int类型
p2 := &p1 // p2 = p1的指针地址,*int类型
*p2++ // *p2 = 1 +1 = 2 = p1
fmt.Println(p1) // 2
fmt.Println(*p2) // 2
*/
// 指针应用 5
}
new函数
package main
import "fmt"
func main() {
// 基本数据类型,即:整型、浮点型、布尔型、字符串、数组、结构体等,泛属于值类型
// 值类型特点:当声明未赋值之前,存在一个默认,即:zero value
// 指针类型属于引用类型,存储的是值的地址,包括后续的切片、man、channel都属于引用类型
// 引用类型,当声明未赋值之前,是没有开启默认空间的,即:没有默认值
var p *int
p = new(int) // new函数就是在创建前,先在内存里开辟一块空间,填入指定类型的一个默认值
fmt.Printf("p的对应:%d\n", *p)
*p = 10
fmt.Println(*p)
fmt.Println(p)
}
数组的声明并赋值
package main
import "fmt"
func main() {
/*
// 数组的特点:长度不可变,一旦创建,长度不能伸缩
// 1、数组声明
// 数组必须限制长度
var arr [3]int
fmt.Println(arr) // 默认值为:[0 0 0]
var names [3]string
fmt.Println(names) // 默认值为:["" "" ""]
// 2、赋值
arr[0] = 10
arr[1] = 20
arr[2] = 30
fmt.Println(arr) // 默认值为:[10 20 30]
names[0] = "lin"
names[1] = "lin2"
names[2] = "lin3"
fmt.Println(names) // 默认值为:[lin lin2 lin3]
// 3、索引
fmt.Println(arr[0]) // 10
fmt.Println(arr[1]) // 20
fmt.Println(arr[2]) // 30
fmt.Println(names[0]) // lin
fmt.Println(names[1]) // lin2
fmt.Println(names[2]) // lin3
*/
/*
// 4、数组的声明并赋值
var names = [3]string{"yuan", "rain", "alvin"}
fmt.Println(names)
var age = [3]int{11, 22, 33}
fmt.Println(age)
*/
/*
// 5、省略长度赋值
var names = [...]string{"yuan", "rain", "alvin"}
fmt.Println(names)
*/
// 6、索引赋值
var names = [3]string{0: "yuan", 1: "rain", 2: "alvin"}
fmt.Println(names)
// go len函数:计算容器数据的长度
fmt.Println(len(names))
fmt.Println(len("ali"))
}
数组的操作
package main
import (
"fmt"
"reflect"
)
func main() {
var names = [3]string{"yuan", "rain", "alvin"}
// 1、索引操作
fmt.Println(names[0]) // 索引取值
names[2] = "Alivin" // 索引修改
fmt.Println(names[2])
// 2、切片操作 数组[start索引:end索引]
var arr = [5]int{11, 12, 13, 14, 15}
s := arr[1:3]
fmt.Println(s, reflect.TypeOf(s)) // [12 13] []int
s1 := arr[1:]
fmt.Println(s1, reflect.TypeOf(s1)) // [12 13 14 15] []int
// 3、遍历数组
var arr2 = [5]int{21, 22, 23, 24, 25}
for i := 0; i < len(arr2); i++ {
fmt.Println(i, arr2[i])
}
// range循环
for i, v := range arr2 {
fmt.Println(i, v)
}
}
切片的底层存储
package main
import "fmt"
func main() {
/*
// 构建切片方式一:通过数组切片操作,获得切片对象
var arr = [3]string{"rain", "erric", "alvin"}
fmt.Println(arr, reflect.TypeOf(arr)) // [rain erric alvin] [3]string
s1 := arr[0:2]
fmt.Println(s1, reflect.TypeOf(s1)) //[rain erric] []string
s2 := arr[1:] // 切片包含:起始地址 长度 容量
fmt.Println(s2, reflect.TypeOf(s2)) //[erric alvin] []string
*/
/*
var a = [5]int{1, 2, 3, 4, 5}
var slice1 = a[:]
var slice2 = a[:2]
fmt.Println(len(slice1), cap(slice1)) // 长度:5 容量:5
fmt.Println(len(slice2), cap(slice2)) // 长度:2 容量:5
fmt.Println(slice1, reflect.TypeOf(slice1)) // [1 2 3 4 5] []int
newSlice := slice1[1:3]
fmt.Println(len(newSlice), cap(newSlice)) // 长度:2 容量:4
fmt.Println(newSlice, reflect.TypeOf(newSlice)) // [2 3] []int
newSlice[1] = 1000
fmt.Println(a)
fmt.Println(slice1)
fmt.Println(slice2)
*/
// 2、 直接声明切片
//var arr = [5]int{11,12,13,14,15}
//s := arr[:]
var s = []int{11, 12, 13, 14, 15}
s1 := s[1:4] // [12,13,14]
fmt.Println(s1, len(s1), cap(s1)) // 长度:3 容量:4
s2 := s[3:] // [14,15]
fmt.Println(s2, len(s2), cap(s2)) // 长度:2 容量:2
s3 := s1[1:2] // [13]
fmt.Println(s3, len(s3), cap(s3)) // 长度:1 容量:3
}
切片练习题
package main
import "fmt"
func main() {
// 练习题 1
s1 := []int{1, 2, 3} // s1 = [1,2,3]
s2 := s1[1:] // s2 = [2,3]
s2[1] = 4 // s2[1] = 3 -> 4 = [2,4]
fmt.Println(s1) // [1,2,4]
// 练习题 2
var a = []int{1, 2, 3} // a = [1,2,3]
b := a // b = a = [1,2,3]
a[0] = 100 // a[0] = 1 -> 100; 此时a = [100,2,3] = b
fmt.Println(b)
}
make函数
package main
import "fmt"
func main() {
/*
// var s = []int{1,2,3,4,5} // 这里声明并初始化了
//var s []int // 这样只声明,没有赋值,没有默认值
//s[0] = 1 // 因为没有默认值,所以没有索引,会报错
// 初始化创建空间
var s = make([]int, 5, 10) // 5为长度,10为容量,便于后续扩展;创建后,前面5个总量内会存储默认的int格式默认值0,后面的因为没有默认值,无法打印显示
fmt.Println(s, len(s), cap(s))
s[0] = 100
fmt.Println(s)
*/
// 练习题 1
a := make([]int, 5) // a = [0 0 0 0 0]
b := a[0:3] // b = [0 0 0]
a[0] = 100 // a[0] = 0 -> 100
fmt.Println(a) // [100 0 0 0 0]
fmt.Println(b) // [100 0 0]
}
append函数
package main
import "fmt"
func main() {
//var s []int
//
//s1 := append(s, 1)
//fmt.Println(s1)
//
//s2 := append(s1, 2, 3, 4, 5)
//fmt.Println(s2)
//
//var t = []int{6, 7, 8}
//s3 := append(s2, t...)
//fmt.Println(s3)
var s4 = make([]int, 3, 10)
s5 := append(s4, 100)
fmt.Println(s5)
}
append原理
package main
import "fmt"
func main() {
/*
a := []int{11, 22, 33}
fmt.Println(len(a), cap(a)) // 3 3
// 这里在a切片的原始数组内,因容量只有3,再次新增字段,源数组无法写入,所以自动扩容了新的数组,c指向新的数组写入44值。
// 新的数组是在原数组基础上做的2倍扩容,所以新的数组容量为6;此时a和c这两个切片实际指向的源数组不一致了,如果变更其中一个切片值,a和c不会联动了
c := append(a, 44)
a[0] = 100
fmt.Println(a)
fmt.Println(c)
*/
/* // make函数
a := make([]int, 3, 10) // [0 0 0]
fmt.Println(a) // [0 0 0]
b := append(a, 11, 22) // b = [0 0 0 11 22]
fmt.Println(a) // [0 0 0]
fmt.Println(b) // [0 0 0 11 22]
a[0] = 100
fmt.Println(a) // [100 0 0]
fmt.Println(b) // [100 0 0 11 22]
*/
// 练习题
arr := [4]int{10, 20, 30, 40}
s1 := arr[0:2] // s1 = [10,20]
s2 := s1 // s2 = s1 = [10 20]
s3 := append(append(append(s1, 1), 2), 3) // s3 = [10 20 1 2 3]
s1[0] = 1000 // s1 = [1000 20]
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(s3)
fmt.Println(arr)
}
append的增删改查
package main
import "fmt"
func main() {
/* var s = []int{1, 2, 3}
fmt.Printf("%p\n", &s)
s = append(s, 4)
fmt.Printf("%p\n", &s)
*/
// 在切片内插入数据
// 1、在切片的前面插入数据
var a = []int{1, 2, 3}
fmt.Println(append([]int{0}, a...))
fmt.Println(append([]int{-1, -2, -3, 0}, a...))
// 2、在切片任意位置插入数据
var b = []int{1, 2, 3, 4, 5}
var i = 2
fmt.Println(append(b[:i], append([]int{6}, b[i:]...)...))
// 3、删除切片内元素
var c = []int{1, 2, 3, 4, 5}
var x = 2
fmt.Println(append(c[:x], c[x+1:]...))
}