编辑代码

package main
import "fmt"
func main () {
//var 数组变量名 [元素数量]Type
var a [3]int             // 定义三个整数的数组
fmt.Println(a[0])        // 打印第一个元素
fmt.Println(a[len(a)-1]) // 打印最后一个元素

// 打印索引和元素
for i, v := range a {
    fmt.Printf("%d %d\n", i, v)
}

// 仅打印元素  range的v始终为集合中对应索引的值拷贝,因此它一般只具有只读性质
for _, v := range a {
    fmt.Printf("%d\n", v)
}
//数组初始化
var q [3]int = [3]int{1, 2, 3}
//“...”省略号,则表示数组的长度是根据初始化值的个数来计算
q := [...]int{1, 2, 3}

//切片默认指向一段连续内存区域,可以是数组,也可以是切片本身
//slice [开始位置 : 结束位置]   slice:表示目标切片对象;
//将 a 切片使用 a[:] 进行操作后,得到的切片与 a 切片一致
//切片的开始和结束位置都设为 0 时,生成的切片将变空

// 声明字符串切片
var strList []string
// 声明一个空切片
var numListEmpty = []int{}
//切片是动态结构,只能与 nil 判定相等,不能互相判定相等。声明新的切片后,可以使用 append() 函数向切片中添加元素
//如果需要动态地创建一个切片,可以使用 make() 内建函数
//make( []Type, size, cap )size 指的是为这个类型分配多少个元素,cap 为预分配的元素数量
b := make([]int, 2, 10)

var a []int
a = append(a, 1) // 追加1个元素
a = append(a, 1, 2, 3) // 追加多个元素, 手写解包方式
a = append(a, []int{1,2,3}...) // 追加一个切片, 切片需要解包 ...就是解包
//切片前闭后开 [start,end)
//因为 append 函数返回新切片的特性,所以切片也支持链式操作
a = append(a[:i], append([]int{x}, a[i:]...)...) // 在第i个位置插入x
//每个添加操作中的第二个 append 调用都会创建一个临时切片,并将 a[i:] 的内容复制到新创建的切片中,然后将临时创建的切片再追加到 a[:i] 中。

//切片复制 copy( destSlice, srcSlice []T) int
//copy() 函数的返回值表示实际发生复制的元素个数
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中
copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置

//从切片中删除元素
//删除开头的元素可以直接移动数据指针
a = []int{1, 2, 3}
a = a[1:] // 删除开头1个元素
a = a[N:] // 删除开头N个元素

a = []int{1, 2, 3}
a = append(a[:0], a[1:]...) // 删除开头1个元素 a[:0]是空切片[],len为0
a = append(a[:0], a[N:]...) // 删除开头N个元素
a = append(a[:i], a[i+N:]...) // 删除中间N个元素
 = a[:len(a)-N] // 删除尾部N个元素


 //map 是引用类型,可以使用如下方式声明:
 //var mapname map[keytype]valuetype
 var mapLit map[string]int
  mapLit = map[string]int{"one": 1, "two": 2}

  var mapAssigned map[string]int
  mapCreated := make(map[string]float32)
  mapCreated["key1"] = 4.5

  //mapCreated := make(map[string]float)等价于mapCreated := map[string]float{} 
scene := make(map[string]int)
// 准备map数据
scene["route"] = 66
scene["brazil"] = 4
scene["china"] = 960
// 声明一个切片保存map数据
var sceneList []string
// 将map数据遍历复制到切片中
for k := range scene {
    sceneList = append(sceneList, k)
}
//使用 delete() 内建函数从 map 中删除一组键值对
delete(scene, "brazil")
//map判断key是否存在,判断方式为value,ok := map[key], ok为true则存在

//go的list是链表结构  并没有具体元素类型的限制
//列表使用 container/list 包来实现,内部的实现原理是双链表
//list 的初始化有两种方法:分别是使用 New() 函数和 var 关键字声明,两种方法的初始化效果都是一致的。
//通过 container/list 包的 New() 函数初始化 list 
l := list.New()
//通过 var 关键字声明初始化 list
//var 变量名 list.List


//双链表支持从队列前方或后方插入元素,分别对应的方法是 PushFront 和 PushBack。
l.PushBack("fist")
l.PushFront(67)
//这两个方法都会返回一个 *list.Element 结构,如果在以后的使用中需要删除插入的元素,则只能通过 *list.Element 配合 Remove() 方法进行删除,这种方法可以让删除更加效率化,同时也是双链表特性之一。
    l := list.New()
    // 尾部添加
    l.PushBack("canon")
    // 头部添加
    l.PushFront(67)
    // 尾部添加后保存元素句柄
    element := l.PushBack("fist")
    // 在fist之后添加high
    l.InsertAfter("high", element)
    // 在fist之前添加noon
    l.InsertBefore("noon", element)
    // 使用
    l.Remove(element)

//遍历双链表需要配合 Front() 函数获取头元素,遍历时只要元素不为空就可以继续进行,每一次遍历都会调用元素的 Next() 函数
l := list.New()
// 尾部添加
l.PushBack("canon")
// 头部添加
l.PushFront(67)
for i := l.Front(); i != nil; i = i.Next() {
    fmt.Println(i.Value)
}
//其中 i:=l.Front() 表示初始赋值,只会在一开始执行一次,
//每次循环会进行一次 i != nil 语句判断,如果返回 false,表示退出循环,
//反之则会执行 i = i.Next()。  

//==对于 nil 来说是一种未定义的操作

//if 还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断
if err := Connect(); err != nil {
    fmt.Println(err)
    return
}
//Connect 是一个带有返回值的函数,err:=Connect() 是一个语句,执行 Connect 后,将错误保存到 err 变量中
//for循环
sum := 0
for i := 0; i < 10; i++ {
    sum += i
}
for j := 0; j < 5; j++ {
    for i := 0; i < 10; i++ {
        if i > 5 {
            break JLoop
        }
        fmt.Println(i)
    }
}
JLoop:
// ...break 语句终止的是 JLoop 标签处的外层循环

//如果 switch 没有表达式,则对 true 进行匹配,因此,可以将 if else-if else 改写成一个 switch
//case 与 case 之间是独立的代码块,不需要通过 break 语句跳出当前 case 代码块
var a = "hello"
switch a {
case "hello":
    fmt.Println(1)
case "world":
    fmt.Println(2)
default:
    fmt.Println(0)
}
//当出现多个 case 要放在一起的时候
var a = "mum"
switch a {
case "mum", "daddy":
    fmt.Println("family")
}

//case 后不仅仅只是常量,还可以和 if 一样添加表达式
var r int = 11
switch {
case r > 10 && r < 20:
    fmt.Println(r)
}
//加入了 fallthrough 关键字来实现紧接着执行下一个 case
var s = "hello"
switch {
case s == "hello":
    fmt.Println("hello")
    fallthrough
case s != "world":
    fmt.Println("world")
}

//Go语言中 goto 语句通过标签进行代码间的无条件跳转
//Go语言中 break 语句可以结束 for、switch 和 select 的代码块,
//另外 break 语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的 for、switch 和 select 的代码块上。

//Go语言里面拥三种类型的函数:
//普通的带有名字的函数
//匿名函数或者 lambda 函数
//方法