指针
指针在go语言中是一个很重要的概念,但比c语言简单多了。
指针简单在:指针不能运算
参数传递:值传递还是引用传递。go语言只有值传递。
值传递验证:
package main
import "fmt"
func swap(a, b int) {
a, b = b, a
}
func main() {
a, b := 3, 4
swap(a, b)
fmt.Println(a, b)
}
image.png
指针传递:
package main
import "fmt"
func swap(a, b int) {
a, b = b, a
}
func swapPrint(a, b *int) {
*a, *b = *b, *a
}
func main() {
a, b := 3, 4
//swap(a, b)
swapPrint(&a, &b)
fmt.Println(a, b)
}
image.png
数组
数据的定义需要声明数组长度。
package main
import "fmt"
func main() {
var arr1 [5]int
arr2 := [3]int{1, 3, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
fmt.Println(arr1, arr2, arr3)
}
image.png
二维数组
package main
import "fmt"
func main() {
var arr1 [5]int
arr2 := [3]int{1, 3, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
fmt.Println(arr1, arr2, arr3)
//二维数组
var grid [4][5]int
var grid2 [4][5]bool
fmt.Println(grid)
fmt.Println(grid2)
}
image.png
range关键字使用
package main
import "fmt"
func main() {
var arr1 [5]int
arr2 := [3]int{1, 3, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
fmt.Println(arr1, arr2, arr3)
//二维数组
var grid [4][5]int
var grid2 [4][5]bool
fmt.Println(grid)
fmt.Println(grid2)
//数组遍历
//for i := 0; i < len(arr3); i++ {
//如上可以写成如下,效果相等,i为下标,v为值
for i, v := range arr3 {
fmt.Println(arr3[i], v)
}
fmt.Println("*******************")
// 如下验证值传递还是引用传递
for i, v := range arr3 {
v++
fmt.Println(arr3[i], v)
}
// 如果只想用值
for _, v := range arr3 {
fmt.Println(v)
}
}
image.png
为什么要用range:
image.png
数组是值类型,可以更好的验证:
package main
import "fmt"
func arrayDemo() {
var arr1 [5]int
arr2 := [3]int{1, 3, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
fmt.Println(arr1, arr2, arr3)
//二维数组
var grid [4][5]int
var grid2 [4][5]bool
fmt.Println(grid)
fmt.Println(grid2)
//数组遍历
//for i := 0; i < len(arr3); i++ {
//如上可以写成如下,效果相等,i为下标,v为值
for i, v := range arr3 {
fmt.Println(arr3[i], v)
}
fmt.Println("*******************")
// 如下验证值传递还是引用传递
for i, v := range arr3 {
v++
fmt.Println(arr3[i], v)
}
// 如果只想用值
for _, v := range arr3 {
fmt.Println(v)
}
}
func printArray(arr [5]int) {
arr[0] = 100
for i, v := range arr {
fmt.Println(arr[i], v)
}
}
func main() {
arr3 := [...]int{2, 4, 6, 8, 10}
printArray(arr3)
fmt.Println("***********")
fmt.Println(arr3)
}
image.png
如果用指针,可以达到一个引用传递的效果。
......
func printArrayPointer(arr *[5]int) {
arr[0] = 100
for i, v := range arr {
fmt.Println(arr[i], v)
}
}
func main() {
arr3 := [...]int{2, 4, 6, 8, 10}
//printArray(arr3)
//fmt.Println("***********")
//fmt.Println(arr3)
printArrayPointer(&arr3)
fmt.Println(arr3)
}
image.png
这里可以看出,数组用起来很麻烦,需要指定数组的长度,更多的使用Slice(切片)
Slice(切片)
切片的使用:
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
// 计算机的区间一般为半开半闭区间,及2,3,4,5
s := arr[2:6]
fmt.Println(arr, s)
}
image.png
为了更好的理解切片,用例如下:
package main
import "fmt"
func main() {
arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
// 计算机的区间一般为半开半闭区间,及2,3,4,5
//s := arr[2:6]
fmt.Println("arr[2:6] = ", arr[2:6])
fmt.Println("arr[:6] = ", arr[:6])
fmt.Println("arr[2:] = ", arr[2:])
fmt.Println("arr[:] = ", arr[:])
}
image.png
arr[2:6],相当于对arr的一个视图
package main
import "fmt"
func updateSlice(s []int) {
s[0] = 100
}
func main() {
arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
// 计算机的区间一般为半开半闭区间,及2,3,4,5
//s := arr[2:6]
//arr[2:6],相当于对arr的一个视图
fmt.Println("arr[2:6] = ", arr[2:6])
fmt.Println("arr[:6] = ", arr[:6])
s1 := arr[2:]
fmt.Println("arr[2:](s1) = ", s1)
s2 := arr[:]
fmt.Println("arr[:](s2) = ", s2)
fmt.Println("After updateSlice(s1)")
updateSlice(s1)
fmt.Println(s1)
fmt.Println(arr)
fmt.Println("After updateSlice(s2)")
updateSlice(s2)
fmt.Println(s2)
fmt.Println(arr)
}
image.png
视图是告诉计算机,这是一个底层数据的视图,如果改掉将等同于整个数据的改动。
也就是说,我们需要用指针达成的效果,可以如下进行:
package main
import "fmt"
func arrayDemo() {
var arr1 [5]int
arr2 := [3]int{1, 3, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
fmt.Println(arr1, arr2, arr3)
//二维数组
var grid [4][5]int
var grid2 [4][5]bool
fmt.Println(grid)
fmt.Println(grid2)
//数组遍历
//for i := 0; i < len(arr3); i++ {
//如上可以写成如下,效果相等,i为下标,v为值
for i, v := range arr3 {
fmt.Println(arr3[i], v)
}
fmt.Println("*******************")
// 如下验证值传递还是引用传递
for i, v := range arr3 {
v++
fmt.Println(arr3[i], v)
}
// 如果只想用值
for _, v := range arr3 {
fmt.Println(v)
}
}
func printArray(arr [5]int) {
arr[0] = 100
for i, v := range arr {
fmt.Println(arr[i], v)
}
}
func printArrayPointer(arr *[5]int) {
arr[0] = 100
for i, v := range arr {
fmt.Println(arr[i], v)
}
}
func printArraySlice(arr []int) {
arr[0] = 100
for i, v := range arr {
fmt.Println(arr[i], v)
}
}
func main() {
var arr1 [5]int
arr3 := [...]int{2, 4, 6, 8, 10}
//printArray(arr3)
//fmt.Println("***********")
//fmt.Println(arr3)
//printArrayPointer(&arr3)
//fmt.Println(arr3)
printArraySlice(arr1[:])
fmt.Println(arr1)
printArraySlice(arr3[:])
fmt.Println(arr3)
}
slice还可以继续切片。
package main
import "fmt"
func updateSlice(s []int) {
s[0] = 100
}
func main() {
arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
// 计算机的区间一般为半开半闭区间,及2,3,4,5
//s := arr[2:6]
//arr[2:6],相当于对arr的一个视图
fmt.Println("arr[2:6] = ", arr[2:6])
fmt.Println("arr[:6] = ", arr[:6])
s1 := arr[2:]
fmt.Println("arr[2:](s1) = ", s1)
s2 := arr[:]
fmt.Println("arr[:](s2) = ", s2)
fmt.Println("After updateSlice(s1)")
updateSlice(s1)
fmt.Println(s1)
fmt.Println(arr)
fmt.Println("After updateSlice(s2)")
updateSlice(s2)
fmt.Println(s2)
fmt.Println(arr)
// slice还可以进一步slice
fmt.Println("Re slice")
fmt.Println(s2)
s2 = s2[:5]
fmt.Println(s2)
s2 = s2[2:]
fmt.Println(s2)
}
image.png
切片的复杂用法
package main
import "fmt"
func updateSlice(s []int) {
s[0] = 100
}
func sliceDemo(arr []int) {
// 计算机的区间一般为半开半闭区间,及2,3,4,5
//s := arr[2:6]
//arr[2:6],相当于对arr的一个视图
fmt.Println("arr[2:6] = ", arr[2:6])
fmt.Println("arr[:6] = ", arr[:6])
s1 := arr[2:]
fmt.Println("arr[2:](s1) = ", s1)
s2 := arr[:]
fmt.Println("arr[:](s2) = ", s2)
fmt.Println("After updateSlice(s1)")
updateSlice(s1)
fmt.Println(s1)
fmt.Println(arr)
fmt.Println("After updateSlice(s2)")
updateSlice(s2)
fmt.Println(s2)
fmt.Println(arr)
// slice还可以进一步slice
fmt.Println("Re slice")
fmt.Println(s2)
s2 = s2[:5]
fmt.Println(s2)
s2 = s2[2:]
fmt.Println(s2)
}
func main() {
arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
//sliceDemo(arr[:])
s1 := arr[2:6]
fmt.Println(s1)
s2 := s1[3:5]
fmt.Println(s2)
}
如上代码,是不报错的:
image.png
涉及到视图的原理:
image.png
image.png
image.png
所以可以如下打印:
......
func main() {
arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
//sliceDemo(arr[:])
fmt.Println("arr=", arr)
s1 := arr[2:6]
s2 := s1[3:5]
fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n", s1, len(s1), cap(s1))
fmt.Printf("s2=%v,len(s2)=%d,cap(s2)=%d\n", s2, len(s2), cap(s2))
}
image.png
切片扩展元素
package main
import "fmt"
func updateSlice(s []int) {
s[0] = 100
}
func sliceDemo(arr []int) {
// 计算机的区间一般为半开半闭区间,及2,3,4,5
//s := arr[2:6]
//arr[2:6],相当于对arr的一个视图
fmt.Println("arr[2:6] = ", arr[2:6])
fmt.Println("arr[:6] = ", arr[:6])
s1 := arr[2:]
fmt.Println("arr[2:](s1) = ", s1)
s2 := arr[:]
fmt.Println("arr[:](s2) = ", s2)
fmt.Println("After updateSlice(s1)")
updateSlice(s1)
fmt.Println(s1)
fmt.Println(arr)
fmt.Println("After updateSlice(s2)")
updateSlice(s2)
fmt.Println(s2)
fmt.Println(arr)
// slice还可以进一步slice
fmt.Println("Re slice")
fmt.Println(s2)
s2 = s2[:5]
fmt.Println(s2)
s2 = s2[2:]
fmt.Println(s2)
}
func main() {
arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
//sliceDemo(arr[:])
fmt.Println("arr=", arr)
s1 := arr[2:6]
s2 := s1[3:5]
fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n", s1, len(s1), cap(s1))
fmt.Printf("s2=%v,len(s2)=%d,cap(s2)=%d\n", s2, len(s2), cap(s2))
s3 := append(s2, 10)
fmt.Println("s3=", s3)
s4 := append(s3, 11)
fmt.Println("s4=", s4)
s5 := append(s4, 12)
fmt.Println("s3,s4,s5=", s3, s4, s5)
fmt.Println("arr=", arr)
}
image.png
这里发现arr的11和12不见了。
image.png
更深入测试
package main
import "fmt"
func printSlice(s []int) {
fmt.Printf("len=%d,cap=%d\n", len(s), cap(s))
}
func main() {
var s []int
for i := 0; i < 100; i++ {
printSlice(s)
s = append(s, 2*i+1)
}
fmt.Println(s)
}
运行结果如下:
len=0,cap=0
len=1,cap=1
len=2,cap=2
len=3,cap=4
len=4,cap=4
len=5,cap=8
len=6,cap=8
len=7,cap=8
len=8,cap=8
len=9,cap=16
len=10,cap=16
len=11,cap=16
len=12,cap=16
len=13,cap=16
len=14,cap=16
len=15,cap=16
len=16,cap=16
len=17,cap=32
len=18,cap=32
len=19,cap=32
len=20,cap=32
len=21,cap=32
len=22,cap=32
len=23,cap=32
len=24,cap=32
len=25,cap=32
len=26,cap=32
len=27,cap=32
len=28,cap=32
len=29,cap=32
len=30,cap=32
len=31,cap=32
len=32,cap=32
len=33,cap=64
len=34,cap=64
len=35,cap=64
len=36,cap=64
len=37,cap=64
len=38,cap=64
len=39,cap=64
len=40,cap=64
len=41,cap=64
len=42,cap=64
len=43,cap=64
len=44,cap=64
len=45,cap=64
len=46,cap=64
len=47,cap=64
len=48,cap=64
len=49,cap=64
len=50,cap=64
len=51,cap=64
len=52,cap=64
len=53,cap=64
len=54,cap=64
len=55,cap=64
len=56,cap=64
len=57,cap=64
len=58,cap=64
len=59,cap=64
len=60,cap=64
len=61,cap=64
len=62,cap=64
len=63,cap=64
len=64,cap=64
len=65,cap=128
len=66,cap=128
len=67,cap=128
len=68,cap=128
len=69,cap=128
len=70,cap=128
len=71,cap=128
len=72,cap=128
len=73,cap=128
len=74,cap=128
len=75,cap=128
len=76,cap=128
len=77,cap=128
len=78,cap=128
len=79,cap=128
len=80,cap=128
len=81,cap=128
len=82,cap=128
len=83,cap=128
len=84,cap=128
len=85,cap=128
len=86,cap=128
len=87,cap=128
len=88,cap=128
len=89,cap=128
len=90,cap=128
len=91,cap=128
len=92,cap=128
len=93,cap=128
len=94,cap=128
len=95,cap=128
len=96,cap=128
len=97,cap=128
len=98,cap=128
len=99,cap=128
[1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55
57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 101 103 105 10
07 109 111 113 115 117 119 121 123 125 127 129 131 133 135 137 139 141 143 145 14
47 149 151 153 155 157 159 161 163 165 167 169 171 173 175 177 179 181 183 185 18
87 189 191 193 195 197 199]
Process finished with the exit code 0
如果声明一个切片,但不初始化数据。
package main
import "fmt"
func printSlice(s []int) {
fmt.Printf("%v,len=%d,cap=%d\n", s, len(s), cap(s))
}
func main() {
//var s []int
//for i := 0; i < 100; i++ {
// printSlice(s)
// s = append(s, 2*i+1)
//}
//fmt.Println(s)
// 如果需要指定一个可变数组,但不知道值,go叫切片,可以如下声明
s2 := make([]int, 16)
// 要求初始化10个数据要存储,但数组长度为32
s3 := make([]int, 10, 32)
printSlice(s2)
printSlice(s3)
}
image.png
Slice(切片)拷贝
package main
import "fmt"
func printSlice(s []int) {
fmt.Printf("%v,len=%d,cap=%d\n", s, len(s), cap(s))
}
func main() {
//var s []int
//for i := 0; i < 100; i++ {
// printSlice(s)
// s = append(s, 2*i+1)
//}
//fmt.Println(s)
fmt.Println("Created Slice")
s1 := []int{2, 4, 6, 8}
// 如果需要指定一个可变数组,但不知道值,go叫切片,可以如下声明
s2 := make([]int, 16)
// 要求初始化10个数据要存储,但数组长度为32
s3 := make([]int, 10, 32)
printSlice(s2)
printSlice(s3)
fmt.Println("Copying slice")
copy(s2, s1)
printSlice(s2)
fmt.Println()
}
image.png
常用的:删除头和尾
package main
import "fmt"
func printSlice(s []int) {
fmt.Printf("%v,len=%d,cap=%d\n", s, len(s), cap(s))
}
func main() {
//var s []int
//for i := 0; i < 100; i++ {
// printSlice(s)
// s = append(s, 2*i+1)
//}
//fmt.Println(s)
fmt.Println("Created Slice")
s1 := []int{2, 4, 6, 8}
// 如果需要指定一个可变数组,但不知道值,go叫切片,可以如下声明
s2 := make([]int, 16)
// 要求初始化10个数据要存储,但数组长度为32
s3 := make([]int, 10, 32)
printSlice(s2)
printSlice(s3)
fmt.Println("Copying slice")
copy(s2, s1)
printSlice(s2)
//删除任意位置
fmt.Println("Deleting elements from slice")
s2 = append(s2[:3], s2[4:]...)
printSlice(s2)
//删除头
fmt.Println("Popping from front")
front := s2[0]
s2 = s2[1:]
fmt.Println(front)
printSlice(s2)
//删除尾
fmt.Println("Popping from back")
tail := s2[len(s2)-1]
s2 = s2[:len(s2)-1]
fmt.Println(tail)
printSlice(s2)
}
image.png
网友评论