范围

  1. range 关键字用于 for 循环中迭代数组、切片、通道或集合(map)的元素,在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对的 key 值。
  2. 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    func main() {
    // 在数组上使用 range 将传入 index 和 value 两个变量
    nums := []int{1,2,3}
    sum := 0
    for _, v := range nums {
    sum += v
    }
    fmt.Println("sum:", sum)

    // range 也可以用在 map 的键值对上。
    kvs := map[string]string{"a":"apple", "b":"banana"}
    for k, v := range kvs {
    fmt.Printf("%s -> %s\n", k, v)
    }

    // range 可以用来枚举 Unicode 字符串。第一个参数是字符的索引,第二个是字符(Unicode 的值)本身。
    for i, c := range "Go" {
    fmt.Println(i, c)
    }
    }

    以上代码输入:
    1
    2
    3
    4
    5
    sum: 6
    b -> banana
    a -> apple
    0 71
    1 111

集合

  1. 集合定义格式

    可以使用内建函数 make 也可以使用 map 关键字来定义集合:

    1
    2
    3
    4
    5
    /* 声明变量,默认 map 是 nil */
    var map_variable map[key_data_type]value_data_type

    /* 使用 make 函数 */
    map_variable := make(map[key_data_type]value_data_type)

    如果不初始化 map,那么就会创建一个 nil mapnil map 不能用来存放键值对

    1
    2
    3
    4
    5
    6
    7
    8
    9
       var countryCapitalMap map[string]string
    countryCapitalMap = make(map[string]string)
    countryCapitalMap["France"] = "Paris"
    countryCapitalMap["China"] = "Beijing"
    countryCapitalMap["Japan"] = "Tokyo"

    for country := range countryCapitalMap {
    fmt.Println(country, "首都是", countryCapitalMap[country])
    }
  2. delete() 函数

    delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key。实例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    func main() {
    var countryCapitalMap map[string]string
    countryCapitalMap = make(map[string]string)
    countryCapitalMap["France"] = "Paris"
    countryCapitalMap["China"] = "Beijing"
    countryCapitalMap["Japan"] = "Tokyo"

    fmt.Println("删除前:")

    for country := range countryCapitalMap {
    fmt.Println(country, "首都是", countryCapitalMap[country])
    }

    delete(countryCapitalMap, "Japan")

    fmt.Println("\n删除了 key 为 Japan 的条目")
    fmt.Println("\n删除后")

    for country := range countryCapitalMap {
    fmt.Println(country, "首都是", countryCapitalMap[country])
    }
    }

    以上输入结果为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    删除前:
    France 首都是 Paris
    China 首都是 Beijing
    Japan 首都是 Tokyo

    删除了 key 为 Japan 的条目

    删除后
    France 首都是 Paris
    China 首都是 Beijing

接口

  1. Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
    1
    2
    3
    4
    5
    6
    7
    8
    /* 定义接口 */
    type interface_name interface {
    method_name1 [return_type]
    method_name2 [return_type]
    method_name3 [return_type]
    ...
    method_namen [return_type]
    }
  2. 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    type Man interface {
    showName() string
    showAge() int
    }

    type People struct {
    name string
    age int
    }

    func (people People) showName() string {
    return people.name
    }

    func (people People) showAge() int {
    return people.age
    }

    func main() {
    var people1 Man
    people1 = People{"张三", 20}

    fmt.Println(people1.showName(), people1.showAge())
    }

    // 张三 20

并发

  1. 通过 go 关键字来开启 goroutine 即可。goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的,语法格式如下:

    1
    go 函数名( 参数列表 )

    例如:

    1
    go f(z, x, y)

    开启一个新的 goroutine

    1
    f(z, x, y)
  2. Go 允许使用 go 语句开启一个新的运行期线程, 即 goroutine,以一个不同的、新创建的 goroutine 来执行一个函数。 同一个程序中的所有 goroutine 共享同一个地址空间。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import (
    "fmt"
    "time"
    )

    func say(s string) {
    for i := 0; i < 5; i++ {
    time.Sleep(100 * time.Millisecond)
    fmt.Println(s)
    }
    }

    func main() {
    go say("Hello")
    say("World")
    }

    以上代码输出:

    1
    2
    3
    4
    5
    6
    7
    Hello
    Hello
    World
    World
    Hello
    Hello
    World

    输出的 hello 和 world 是没有固定先后顺序。因为它们是两个 goroutine 在执行

通道

  1. 通道 channel 是用来传递数据的一个数据结构。

    1
    2
    3
    ch := make(chan int) // 声明 ch 通道
    ch <- v // 把 v 发送到通道 ch
    v := <- ch // 从 ch 接受数据并赋值给 v

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    func sum(s []int, c chan int) {
    num := 0
    for _,v := range s {
    num += v
    }
    c <- num
    }

    func main() {
    s := []int{1, 2, 3, 4, 5, 6}
    c := make(chan int)

    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)

    x, y := <-c, <-c

    fmt.Printf("x=%d,y=%d,x+y=%d", x, y, x+y)
    }

    // x=15,y=6,x+y=21
  2. 通道缓存区

    通道可以设置缓冲区,通过 make 的第二个参数指定缓冲区大小:

    1
    ch := make(chan int, 100)

    带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放在缓冲区里面,可以等待接收端去获取数据,而不是立刻需要接收端去获取数据。

  3. 遍历通道与关闭通道

    通过 range 关键字来实现遍历读取道的数据,类似于与数组或切片。格式如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    func sum(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
    c <- x
    x, y = y, x+y
    }
    close(c)
    }

    func main() {
    c := make(chan int, 10)
    go sum(cap(c), c)
    for i := range c {
    fmt.Print(i, " ")
    }
    }

    // 0 1 1 2 3 5 8 13 21 34