- 获取命令行参数
- init函数
- 局部变量和全局变量
- 变量的内存和变量的地址
- 指针变量的使用
- new函数的使用
- 值传递
- 引用传递
- 随机数的使用
- 数组
- 切片
- map
- 结构体
- 可见性规则
package main
import (
. "fmt"
"math/rand"
"os"
"time"
)
// init函数,包被引用时,自动调用的函数,引用包优先当前包
func init() {
println("main包的init函数")
}
// 获取命令行参数
func demo1() {
list := os.Args
for i := range list {
Printf("list[%d] = %v\n", i, list[i])
}
}
// 局部变量和全局变量
func demo2() {
a := 1
{
a := 2
println("内部 a = ", a)
}
println("外部 a = ", a)
}
// 变量的内存和变量的地址
func demo3() {
// 内存1
a := 1
// 地址&a
p := &a
Printf("a = %v, p = %v\n", a, p)
}
// 指针变量的使用
// 不能操作没有合法指向的指针
func demo4(a *int) (result *int) {
// 修改地址a中的值
*a = 666
result = a
return
}
// new函数的使用
func demo5() {
// p是*int
p := new(int)
Printf("这里是new函数的使用,p.type = %T, p = %v\n", p, p)
}
// 值传递
func demo6(a int) {
println("这里是值传递,a = ", a)
}
// 引用传递
func demo7(p *int) {
println("这里是引用传递,p = ", p)
}
// 随机数的使用
func demo8() {
// 种子参数一样,生成随机数结果固定
a := rand.Int()
// 生成指定范围内的随机数
b := rand.Intn(100)
// 按时间生成随机数
c := rand.Intn(int(time.Now().UnixNano()))
Printf("生成的随机数为 a = %d,b = %d, c = %d", a, b, c)
}
// 数组和切片
func demo9() {
// 全量初始化
array := [5]int{1, 2, 3, 4, 5}
// 部分初始化
array1 := [5]int{1, 2}
// 指定初始化
array2 := [5]int{2: 2}
// 二维数组
array3 := [5][2]int{1: {2, 4}}
Printf("这里是数组,array = %v,array1 = %v,array2 = %v, array3 = %v\n", array, array1, array2, array3)
// 数组可以比较和赋值
Printf("这里是数组赋值比较,array == array1 %v\n", array == array1)
// 数组做函数参数是值拷贝
func(arr [5]int) {
Printf("这里是数组参数传递值拷贝,arr == array %v,&arr == &array %v\n", arr == array, &arr == &array)
}(array)
// 数组指针做函数参数
func(p *[5]int) {
Printf("这里是数组指针参数传递,p == &array %v, p = %v\n", p == &array, p)
}(&array)
// 冒泡排序
array4 := func() (result [5]int) {
for i := 0; i < 5; i++ {
b := rand.Intn(100)
result[i] = b
}
return
}()
array5 := func(arr [5]int) (result [5]int) {
for i := 0; i < 5-1; i++ {
for j := 0; j < 5-1-i; j++ {
if arr[j] > arr[j+1] {
arr[j], arr[j+1] = arr[j+1], arr[j]
}
}
}
return arr
}(array4)
Printf("这里是数组,array4 = %v,排序后,array5 = %v\n", array4, array5)
// [...]int{} ...代表不确定长度,根据初始化元素数量推测长度
array6 := [...]int{1}
Printf("这里是数组,不定长数组array6 = %v,排序后,array6.type = %T\n", array6, array6)
// 数组切片slice
// 数组定义后就不可以更改长度,从而提供了数组切片,它通过内部指针和相关属性引用数组片段,以实现变长方案
// 切片slice并不是真正的动态数组,而是一个引用类型,slice底层总是指向一个数组,声明也可以像数组一样,只是不需要长度
// array[begin:end:cap],begin起始下标,end结束下标(不包含),cap容量=cap-begin,缺省为原数组长度
array7 := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := array7[0:4:5]
// 缺省cap为原数组长度
slice2 := array7[5:8]
// 从第5开始,截取到末尾,容量为数组长度-5
slice3 := array7[5:]
// 从0开始,截取到8,容量也为8
slice4 := array7[:8]
// 切片的底层都是指向一个数组
slice5 := slice4[:9]
Printf("这里是切片,slicer = %v,slicer.type = %T,slicer2 = %v,slicer2.type = %T\n", slice, slice, slice2, slice2)
Printf("这里是切片,slicer3 = %v,slicer3.type = %T,slicer4 = %v,slicer4.type = %T\n", slice3, slice3, slice4, slice4)
Printf("这里是切片,slicer5 = %v,slicer5.type = %T\n", slice5, slice5)
// append,在切片的末尾进行追加
var slice6 []int = append(slice5, -1, -2, -3)
Printf("这里是切片,slicer5追加后: slicer6 = %v,slicer6.type = %T\n", slice6, slice6)
// 切片追加后,如果超出cap,那么将以两倍形式扩容
// 切片做函数参数,是引用传递,不是值拷贝
func(s1 []int) {
oldCap := cap(s1)
for i := 0; i < 10; i++ {
if cap(s1) > oldCap {
Printf("这里是切片,cap(s1) = %v,oldCap = %v\n", cap(s1), oldCap)
oldCap = cap(s1)
}
s1 = append(s1, -1)
}
}(array7[:1:1])
}
// map(映射,字典)一个无序的K-V结构
func demo10() {
// map中的K是唯一的,且必须支持==和!=操作的类型,切片/函数以及包含切片的结构类型,不可作为K,因为存在引用语义,会编译错误
var map1 map[string]string
// map 只有 len, 没有cap
Printf("这里是map,map1 = %v, map1.type = %T, len(map) = %v\n", map1, map1, len(map1))
// map通过make来进行初始化
map1 = make(map[string]string)
// 可指定长度,不足时可自动扩容,扩容机理类似append
map1 = make(map[string]string, 1)
map1["a"] = "map-a"
map1["b"] = "map-b"
Printf("这里是map,初始化后 map1 = %v, map1.type = %T, len(map) = %v\n", map1, map1, len(map1))
// 重复赋值即为修改内容
map1["a"] = "map-a-a"
Printf("这里是map,修改内容 map1 = %v, map1.type = %T, len(map) = %v\n", map1, map1, len(map1))
// 删除内容
delete(map1, "a")
Printf("这里是map,删除内容 map1 = %v, map1.type = %T, len(map) = %v\n", map1, map1, len(map1))
// 遍历map
for k, v := range map1 {
Printf("这里是map,遍历内容 map1[%v] = %v\n", k, v)
}
// 判断元素是否存在map
key := "a"
value, result := map1[key]
if result {
Printf("这里是map,判断元素Key存在: result = %v, map1[%v] = %v\n", result, key, value)
} else {
Printf("这里是map,判断元素Key存在: result = %v\n", result)
}
// map做函数参数是引用传递
func(m1 map[string]string) {
m1["a"] = "m1-a"
Printf("这里是map,map做函数参数为引用传递: m1 = %v, map1 = %v\n", m1, map1)
}(map1)
}
// 结构体
func demo11() {
// 结构体可被比较与赋值,具有值传递与引用传递
type Student struct {
Id int
Name string
Age int
Sex byte
}
// 顺序初始化
var s1 = Student{1, "radish", 20, 'm'}
Printf("这里是结构体,顺序初始化: s1 = %v, s1.type = %T\n", s1, s1)
// 指定成员初始化,未初始化赋值为0
s2 := Student{Id: 1, Name: "radish"}
Printf("这里是结构体,指定成员初始化: s2 = %v, s2.type = %T\n", s2, s2)
// 结构体的指针变量初始化
var p1 *Student
p1 = &Student{1, "radish", 20, 'm'}
Printf("这里是结构体,结构体指针变量顺序初始化: p1 = %v, p1.type = %T\n", p1, p1)
p2 := &Student{Name: "redish"}
Printf("这里是结构体,结构体指针变量指定成员初始化: p2 = %v, p2.type = %T\n", p2, p2)
// 操作成员
s1.Id = 2
s1.Name = "radish40"
Printf("这里是结构体,操作成员: s1 = %v, s1.type = %T\n", s1, s1)
// 通过指针操作成员
// p1.Id和(*p1).id完全等价,只能使用.运算符
p1 = new(Student)
p1.Id = 2
p1.Name = "radish40"
Printf("这里是结构体,通过指针操作成员: p1 = %v, p1.type = %T\n", p1, p1)
}
func main() {
var (
a = 10
p = &a
)
demo1()
demo2()
demo3()
demo4(p)
demo5()
demo6(a)
demo7(p)
demo8()
demo9()
demo10()
demo11()
}