struct slice和映射

结构体struct 是一组字段 field,使用.访问

type Vertex struct {
    X int
    Y int
}

花括号的使用原来落在了这里
v :=Vertex{1, 2}
v.x = 5
fmt.Println(v.x)

结构体的指针可以当作结构体变量使用(语法糖)

v :=Vertex{1, 2}
p = &v
p.X 等价于 (*p).X 等价于 v.X 等价于1

结构体可以单独给某个字段赋值,其余会隐式赋值默认值

v2 = Vertex{X: 1}  // Y:0 被隐式地赋予
v2内容为{1,0}

数组

声明
var a [10]int

可以基于数组,创建一个切片,动态扩展,但又不同于oc中的mutableArray,切片更像是数组的引用,对切片的修改会影响到数组和基于该数组的其他切片.或者说不是mutableCopy性质的.

primes := [6]int{2, 3, 5, 7, 11, 13}
var s []int = primes[1:4]
fmt.Println(s)
输出为2,3,4
包含冒号前,不包括冒号后的..

因为上面切片的特性,所以常见直接初始化切片,并直接操作切片,虽然其背后是有一个匿名数组存在

q := []int{2, 3, 5, 7, 11, 13}
创建一个匿名数组,然后构建一个引用了它的切片,保存为q

切片使用冒号切片,可以不填来默认上下界

var a [10]int
以下切片等价
a[0:10]
a[:10]
a[0:]
a[:]

切片的容量是从自己第一个开始,到其依赖的底层数组最后一个(最多就到这里了),切片的长度是自己第一个到自己最后一个的元素数.所以容量>=长度

package main

import "fmt"

func main() {
    s := []int{2, 3, 5, 7, 11, 13}
    printSlice(s)

    // 截取切片使其长度为 0
    s = s[:0]
    printSlice(s)

    // 拓展其长度
    s = s[:4]
    printSlice(s)

    // 舍弃前两个值
    s = s[2:]
    printSlice(s)
}

func printSlice(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

输出
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]

使用make来创建切片,这里很关键,实践中很多这种用法

a := make([]int, 5)          // len(a)=5
b := make([]int, 0, 5)         // len(b)=0, cap(b)=5
再切两次
b = b[:cap(b)]                 // len(b)=5, cap(b)=5
b = b[1:]                      // len(b)=4, cap(b)=4

内建函数append向切片中添加元素,可无限添加,切片的底层数组会动态调整

package main

import "fmt"

func main() {
    var s []int
    printSlice(s)

    // 添加一个空切片
    s = append(s, 0)
    printSlice(s)

    // 这个切片会按需增长
    s = append(s, 1)
    printSlice(s)

    // 可以一次性添加多个元素
    s = append(s, 2, 3, 4)
    printSlice(s)
}

func printSlice(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

输出
len=0 cap=0 []
len=1 cap=2 [0]
len=2 cap=2 [0 1]
len=5 cap=8 [0 1 2 3 4]

使用for range来遍历切片,返回值为索引和值拷贝,可以使用_来忽略

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
    for i, v := range pow {
        fmt.Printf("2**%d = %d\n", i, v)
    }
    
    for i,_ := range pow{
        //do something with index i    
    }
}

​输出
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128

go中的字典map称为映射,可以使用make声明,再设置值(alloc即视感)

注意映射最后的一个,不能省略

package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m map[string]Vertex

func main() {
    m = make(map[string]Vertex)
    m["Bell Labs"] = Vertex{
        40.68433, -74.39967,
    }
    fmt.Println(m["Bell Labs"])
    
    //或者可以这样
    m["Bell Labs"] = {40.68433, -74.39967,}
}
输出
{40.68433 -74.39967}

也可以在初始化时候直接赋值,此时不用make

var m = map[string]string{
    "Bell Labs": "贝尔实验室",
    "Google":"谷歌",
}

//增,改
m["Google"] = "跟中国有不解之缘"

//删
delete(m,"Google")

//get
s = m["Google"]

//get同时判断是否存在该key
value,hasKey := m["Google"] 

value 为 "跟中国有不解之缘"
hasKey 为 true

使用函数做参数

package main

import (
    "fmt"
    "math"
)

func compute(fn func(float64, float64) float64) float64 {
    return fn(3, 4)
}

func main() {
    hypot := func(x, y float64) float64 {
        return math.Sqrt(x*x + y*y)
    }
    fmt.Println(hypot(5, 12))

    fmt.Println(compute(hypot))
    fmt.Println(compute(math.Pow))
}

输出
13
5
81

标签: golang, c

添加新评论