本文已参与「新人创作礼」活动,一起开启掘金创作之路。
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)
}
}
- 使用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
}
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
9. import
创建目录结构:
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)
}
结果:
自定义代码块