数组

同一种数据类型元素的集合。数组的长度是数组类型的一部分

  1. var a [3]int

数组的初始化(如果不初始化,默认元素都是零值)

  1. // 1
  2. a1 = [3]bool{true, true, true}
  3. // 2 根据初始值自动推断
  4. a2 = [...]int{1,2,3,4,5,6,7,8,9}
  5. // 3 根据索引初始化
  6. a3 := [5]int{0:1, 4:2}

数组的遍历

  1. citys := [...]string{"上海""深圳""广州"}
  2. // 索引编译
  3. for i:=0;i<len(citys);i++{
  4. fmt.Println(citys[i])
  5. }
  6. // for range
  7. for i, v := range citys {
  8. }

多维数组

  1. // [[1 2] [3 4] [5 6]]
  2. var a11 [3][2]int
  3. a11 = [3][2]int {
  4. [2]int {1,2},
  5. [2]int {3,4},
  6. [2]int {5,6},
  7. }

多维数组的遍历

  1. for _, v1 := range a11 {
  2. for _, v2 := range v1 {
  3. }
  4. }

数组是值类型,赋值时总是创建了新的地址

  1. b1 := [3]int {1,2,3}
  2. b2 := b1 // 赋值时创建是创建了新的地址,并放入,修改b2不影响b1
  3. b2[0] = 100

数组支持== !=, 因为内存总是被初始化过的

[n]T表示指针数组, [n]T 表示数组指针

切片

Go 语言中的切片有三种初始化的方式:

  1. 通过下标的方式获得数组或者切片的一部分;
  2. 使用字面量初始化新的切片;
  3. 使用关键字 make 创建切片:
    1. arr[0:3] or slice[0:3]
    2. slice := []int{1, 2, 3}
    3. slice := make([]int, 10)

切片是引用类型,不支持直接比较,只能和nil比较。切片的本质就是一个框,框住了一块连续的内存,属于引用类型,真正的数据都是来自于底层数组。

  1. // 与nil 比较
  2. t == nil

切片拥有自己的长度和容量,可以通过len()求长度,使用内置的cap()求切片的容量

可以使用append方法来为切片添加元素,索引不能超过容量,否则会产生越界错误.使用append相当于创建了一块新的内存给切片。(底层数组变了,即地址变了)

  1. a3 = append(a3, 111)

使用**copy**来复制切片,会划分一块新的地址。简单的赋值只是做了地址引用,而使用copy则是划分了新的地址给它

  1. a1 := []int{1,3,5}
  2. a2 := a1
  3. var 3 make([]int, 0, 3)
  4. copy(a3, a1)

切片没有删除的专用方法,需要使用切片的本身特性来删除。 …运算符表示将一个切片的所有元素追加到另一个切片里

  1. a := []int{1,2,3,4}
  2. // 删除索引为2的元素
  3. a = append(a[:2], a[3:]...)

字典(哈希表)

go语言中提供映射关系,无序的,是引用类型(需要初始化)

  1. var a map[string]int
  2. a = make(map[string]int, 0) // 自动扩容
  3. a["1"] = 1
  4. value, ok := a["1"] // 约定俗称使用ok接收返回的布尔值
  5. // 使用key value来表示键值对
  6. hash := map[string]int{
  7. "1": 2,
  8. "3": 4,
  9. "5": 6,
  10. }

遍历

  1. for k,v := range a {}
  2. // 只遍历key
  3. for k := range a {}
  4. // 只遍历value
  5. for _,v := range a {}

删除

  1. delete(a,"1")

map和slice的组合: 要初始化

  1. 元素为map类型的切片
  1. var s1 = make([]map[int]string, 0, 10) //初始化slice,访问第一个元素报越界错误
  2. var s2 = make([]map[int]string, 1, 10) //初始化slice,访问第一个元素报未初始化map错误
  3. s1[0] = make(map[int]string, 1)
  4. s1[0][100] = "abc"
  1. 值为切片类型的map
  1. var m1 = make(map[string][]int, 10)
  2. m1['北京'] = []int{10, 20, 30}

字符串

utf-8。

go语言中的双引号只能用双引号。go语言中的单引号包裹的是字符。

字符:’h’ ‘你’ ,单独的字母,汉字,符号表示一个字符。

一个AscII等于一个字节(8位)
一个utf8编码的汉字等于3个字节

多行字符串

  1. s2=`123
  2. 456
  3. 789
  4. `

字符串常用操作

  • len(str)
  • +fmt.Sprintf
  • strings.Split 分割
  • strings.contains 包含
  • strings.HasPrefix, strings.HasSuffix 前缀/后缀判断
  • strings.Index(), strings.LastIndex() 子串出现的位置
  • strings.Join(a[]string, sep string) join操作

    流程控制

    if

  1. if age > 18 {
  2. } else if {
  3. } else {
  4. }

作用域

  1. if age := 19; age >18 { //age只在if条件判断中生效
  2. } else {
  3. }

不支持三元操作符(三目运算符) > a > b ? a : b

switch

switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上直下逐一测试,直到匹配为止。 Golang switch 分支表达式可以是任意类型,不限于常量。可省略 break,默认自动终止。

  1. switch var1 {
  2. case val1:
  3. ...
  4. case val2:
  5. ...
  6. default:
  7. ...
  8. }

switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。

  1. switch x.(type){
  2. case type:
  3. statement(s)
  4. case type:
  5. statement(s)
  6. /* 你可以定义任意个数的case */
  7. default: /* 可选 */
  8. statement(s)
  9. }

select

select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。
select 是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收。 select 随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该总是可运行的。

  1. select {
  2. case communication clause :
  3. statement(s);
  4. case communication clause :
  5. statement(s);
  6. /* 你可以定义任意数量的 case */
  7. default : /* 可选 */
  8. statement(s);
  9. }

使用场景:

  1. 超时判断 ```go var resChan = make(chan int) // do request func test() { select { case data := <-resChan:
    1. doData(data)
    case <-time.After(time.Second * 3):
    1. fmt.Println("request time out")
    } }

func doData(data int) { //… }

  1. 2. 退出
  2. ```go
  3. //主线程(协程)中如下:
  4. var shouldQuit=make(chan struct{})
  5. fun main(){
  6. {
  7. //loop
  8. }
  9. //...out of the loop
  10. select {
  11. case <-c.shouldQuit:
  12. cleanUp()
  13. return
  14. default:
  15. }
  16. //...
  17. }
  18. //再另外一个协程中,如果运行遇到非法操作或不可处理的错误,就向shouldQuit发送数据通知程序停止运行
  19. close(shouldQuit)
  1. 判断是否阻塞 ```go //在某些情况下是存在不希望channel缓存满了的需求的,可以用如下方法判断 ch := make (chan int, 5) //… data:=0 select { case ch <- data: default: //做相应操作,比如丢弃data。视需求而定 }
  1. <a name="kAeeG"></a>
  2. ## for
  3. ```go
  4. for i :=0;i<10;i++{
  5. }

可以省略初始语句

  1. for ;i<10:i++{
  2. }

可以省略执行语句

  1. for i < 10{
  2. i++
  3. }

无限循环

  1. for {
  2. }

for range:遍历数组,切片,字符串,map及通道

  1. s := "hello"
  2. for i, v := range s {
  3. fmt.Printf("%d %c\n", i, v)
  4. }

跳出循环break

跳出指定循环

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. J:
  7. for j := 0; j < 5; j++ {
  8. for i := 0; i < 10; i++ {
  9. if i > 6 {
  10. break J //现在终止的是j 循环,而不是i的那个
  11. }
  12. fmt.Println(i)
  13. }
  14. }
  15. }

跳过continue