golang 基础第三篇

163 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

7.字典(map)

哈希表 , key=>value, 存储的key是经过哈希运算的

package main
​
import "fmt"func main() {
    //1. 定义一个字典
    //学生id ==> 学生名字  idNames
    var idNames map[int]string //定义一个map,此时这个map是不能直接赋值的,它是空的
​
    idNames[0] = "duke"
    idNames[1] = "lily"for key, value := range idNames {
        fmt.Println("key:", key, ", value:", value)
    }
}
​

1585898733163.png

  1. 使用map之前,一定要对map进行分配空间
package main
​
import "fmt"func main() {
    //1. 定义一个字典
    //学生id ==> 学生名字  idNames
    var idNames map[int]string //定义一个map,此时这个map是不能直接赋值的,它是空的//2. 分配空间,使用make,可以不指定长度,但是建议直接指定长度,性能更好
    idScore := make(map[int]float64)   //这个也是正确的
    idNames = make(map[int]string, 10) //建议使用这种方式//3. 定义时直接分配空间
    //idNames1 := make(map[int]string, 10) //这是最常用的方法
​
    idNames[0] = "duke"
    idNames[1] = "lily"//4. 遍历map
    for key, value := range idNames {
        fmt.Println("key:", key, ", value:", value)
    }
​
    //5. 如何确定一个key是否存在map中
    //在map中不存在访问越界的问题,它认为所有的key都是有效的,所以访问一个不存在的key不会崩溃,返回这个类型的零值
    //零值:  bool=》false, 数字=》0,字符串=》空
    name9 := idNames[9]
    fmt.Println("name9:", name9)               //空
    fmt.Println("idScore[100]:", idScore[100]) //0//无法通过获取value来判断一个key是否存在,因此我们需要一个能够校验key是否存在的方式
    value, ok := idNames[1] //如果id=1是存在的,那么value就是key=1对应值,ok返回true, 反之返回零值,false
    if ok {
        fmt.Println("id=1这个key是存在的,value为:", value)
    }
​
    value, ok = idNames[10]
    if ok {
        fmt.Println("id=10这个key是存在的,value为:", value)
    } else {
        fmt.Println("id=10这个key不存在,value为:", value)
    }
​
    //6. 删除map中的元素
    //使用自由函数delete来删除指定的key
    fmt.Println("idNames删除前:", idNames)
    delete(idNames, 1)   //"lily"被kill
    delete(idNames, 100) //不会报错
    fmt.Println("idNames删除后:", idNames)
​
    //并发任务处理的时候,需要对map进行上锁 //TODO
}
​

1585899844151.png

8. 函数

package main
​
import "fmt"//1.函数返回值在参数列表之后
//2.如果有多个返回值,需要使用圆括号包裹,多个参数之间使用,分割
func test2(a int, b int, c string) (int, string, bool) {
    return a + b, c, true
}
​
func test3(a, b int, c string) (res int, str string, bl bool) {
​
    var i, j, k int
    i = 1
    j = 2
    k = 3
    fmt.Println(i, j, k)
​
    //直接使用返回值的变量名字参与运算
    res = a + b
    str = c
    bl = true//当返回值有名字的时候,可以直接简写return
    return//return a + b, c, true
}
​
//如果返回值只有一个参数,并且没有名字,那么不需要加圆括号
func test4() int {
    return 10
}
​
func main() {
    v1, s1, _ := test2(10, 20, "hello")
    fmt.Println("v1:", v1, ",s1:", s1)
​
    v3, s3, _ := test3(20, 30, "world")
    fmt.Println("v3:", v3, ", s3:", s3)
}
​

内存逃逸:

package main
​
import "fmt"func main() {
    p1 := testPtr1()
    fmt.Println("*p1:", *p1)
}
​
//定义一个函数,返回一个string类型的指针, go语言返回写在参数列表后面
func testPtr1() *string {
    name := "Duke"
    p0 := &name
    fmt.Println("*p0:", *p0)
​
    city := "深圳"
    ptr := &city
    return ptr
}
​
go build -o test.exe --gcflags "-m -m -l" 11-内存逃逸.go  > 1.txt  2>&1
​
grep -E "name|city" 1.txt --color

1585902031122.png

9. import

创建目录结构:

1585903432739.png

add.go

package add
​
func add(a, b int) int {
    return a + b
}

sub.go

package sub
​
//在go语言中,同一层级目录,不允许出现多个包名
func Sub(a, b int) int {
    test4() //由于test4与sub.go在同一个包下面,所以可以使用,并且不需要sub.形式
    return a - b
}

utils.go

package sub
​
//package utils //不允许出现多个包名
​
import "fmt"
​
func test4() {
    fmt.Println("this is test4() in sub/utils!")
}

main.go

package main
​
import (
    SUB "12-import/sub" //SUB是我们自己重命名的包名
    //"12-import/sub" //sub是文件名,同时也是包名
    . "12-import/sub" //.代表用户在调用这个包里面的函数时,不需要使用包名.的形式,不见一使用的
    "fmt"
)
​
func main() {
    //res := sub.Sub(20, 10) //包名.函数去调用
    res := SUB.Sub(20, 10) //包名.函数去调用
    fmt.Println("sub.Sub(20,10) =", res)
​
    res1 := Sub(30, 20)
    fmt.Println("Sub(30, 20) :", res1)
​
    //这个无法被调用,是因为函数的首写字母是小写的
    //如果一个包里面的函数想对外提供访问权限,那么一定要首写字母大写,
    // 大写字母开头的函数相当于 public,
    // 小写字母开头的函数相当于 private, 只有相同包名的文件才能使用
    //add.add(10,20)
}

结果:

1585903519834.png

自定义代码块

1585904088510.png