Golang学习之路3-基础认识(下)
@
前言
学习一门语言,先认识下Golang的基础语法,例如变量定义、数据类型等等。
一、数组
1.定长数组
1)定长数组 (5容量)
nums := [5]string{"aa", "bb", "cc"}
2)遍历数组,方式一
3)遍历数组,方式二 (常用)
package main
import "fmt"
func main1() {
// 定长数组 (5容量)
names := [5]string{"aa", "bb", "cc"}
names[3] = "dd"
// 遍历数组,方式一
for i := 0; i < len(names); i++ {
fmt.Println(names[i])
}
// 遍历数组,方式二 (常用)
for key, value := range names {
// 可忽略key使用下划线如:for _, value := range names {
fmt.Println(key, value)
}
// 忽略两个需要用=而不能使用:= 如:for _, _ = range names
}
2.不定长数组
1)不定长数组:
names := []string{"aa", "bb", "cc"}
2)追加数据重新赋值会给自己
cap:查看容量,如果容量不足,会动态扩充容量正常是当前容量的2倍
names = append(names, "dd")
3) 数组切片,左闭右开
// 打印 0-1 索引的数据
fmt.Println(names[:2])
// 打印 1-2 索引的数据
fmt.Println(names[1:3])
// 打印 2-n 索引的数据
fmt.Println(names[2:])
4)创建指定长度及指定容量的数组
// 创建指定长度及指定容量的数组
names2 := make([]string, 10, 50)
names2[0] = "a"
5)如果数组切片赋值,不共享数据则使用:copy
// 基于以上,如果不共享数据则使用:copy
namesList := []string{"aa", "bb"}
copyList := make([]string, 2, 50)
copy(copyList, namesList)
fmt.Println("修改前:", namesList, copyList)
namesList[0] = "cc"
fmt.Println("修改后:", namesList, copyList)
完整代码:
package main
import "fmt"
func main() {
// 不定长数组
names := []string{"aa", "bb", "cc"}
fmt.Println("追加前的容量:", cap(names))
// 追加数据重新赋值会给自己
names = append(names, "dd")
fmt.Println("追加后的容量:", cap(names))
// 数组切片&创建新数组,左闭右开
names1 := names[:2] // 建新数组,数据共享的
fmt.Println(names1)
names[0] = "修改后的"
fmt.Println(names1)
names = append(names, "追加数据不共享AA")
fmt.Println(names, names1)
// 基于以上,如果不共享数据则使用:copy
namesList := []string{"aa", "bb"}
copyList := make([]string, 2, 50)
copy(copyList, namesList)
fmt.Println("修改前:", namesList, copyList)
namesList[0] = "cc"
fmt.Println("修改后:", namesList, copyList)
// 创建指定长度及指定容量的数组
names2 := make([]string, 10, 50)
names2[0] = "a"
}
二、map
map 一种无序的键值对, 它是数据结构 hash 表的一种实现方式。map工作方式就是:定义键和值(key、value),并且可以获取,设置和删除其中的值。
1.使用关键字 map 来声明
names := map[string]string{"key": "value"}
// 使用关键字 map 来声明
names := map[string]string{"ppl": "yes", "gsxl": "no"}
for key, value := range names {
fmt.Println(key, value)
}
2.使用 make 来声明
// 使用make来声明
mapAge := make(map[string]int)
3.添加元素
// 赋值:key=ppl value=18
mapAge["ppl"] = 18
4.检索key的value是否存在
检索不到默认返回0
// 检索key的value
age, ok := mapAge["ppl"]
if ok {
fmt.Println("age:", age)
}
// 检索不到返回0
age, ok := mapAge["ppl1"]
5.删除元素
函数没有返回值
// 删除map的key:value,不存在也不会报错,存在则删除
delete(names, "gsxl")
fmt.Println(names)
6.遍历map
for key, value := range names {}
names := map[string]string{"ppl": "yes", "gsxl": "no"}
for key, value := range names {
fmt.Println(key, value)
}
7.map的注意点
- map是引用类型,当map赋值给一个新变量指针是指向同一个内部数据结构,因此任一改变另一跟随改变
- 须指定 key, value 的类型,且数据类型必须与定义一致
- 无序性,key唯一性
- value可以为任意类型
- key可以为基础数据类型(例如 bool, 数字类型,字符串), 不能为数组,切片,map,它的取值必须是能够使用 == 进行比较
- 线程不安全, 写入并发时(goroutine)需要加锁,另外也不能并发的读写,否则错误
完整代码:
package main
import "fmt"
func main() {
// 使用关键字 map 来声明
names := map[string]string{"ppl": "yes", "gsxl": "no"}
for key, value := range names {
fmt.Println(key, value)
}
// 使用make来声明
mapAge := make(map[string]int)
// 赋值:key=ppl value=18
mapAge["ppl"] = 18
// 检索key的value
age, ok := mapAge["ppl1"]
if ok == false {
fmt.Println("age:", age)
}
// 删除map的key:value
delete(names, "gsxl")
fmt.Println(names)
}
三、指针
什么是指针?
一个指针变量指向了一个值的内存地址,内部垃圾回收机制(gc)。
1.使用指针& 及 *
- 变量指针存储地址:&name
- 使用指针访问值:*ptr
// 声明实际变量
name := "ppl"
// 声明指针变量且存储地址=&name
ptr := &name
fmt.Println("name:", name)
fmt.Println("name ptr:", ptr)
fmt.Println("name ptr使用指针访问值:", *ptr)
2.空指针
空指针:nil,既空值如Python的None,mysql的null
// 空指针:nil,既空值如Python的None,mysql的null
var ptrNil *string
// 指针做判断 != 与 ==
if ptrNil == nil {
fmt.Println("ptrNil:", ptrNil)
}
完整代码
package main
import "fmt"
func main() {
// 声明实际变量
name := "ppl"
// 声明指针变量且存储地址=&name
ptr := &name
fmt.Println("name:", name)
fmt.Println("name ptr:", ptr)
fmt.Println("name ptr使用指针访问值:", *ptr)
// 使用new关键字定义
name1 := new(string)
*name1 = "ppl"
fmt.Println(name1)
fmt.Println(*name1)
fmt.Println("strPtr():", strPtr(*name1))
// 空指针:nil,既空值如Python的None,mysql的null
var ptrNil *string
// 指针做判断 != 与 ==
if ptrNil == nil {
fmt.Println("ptrNil:", ptrNil)
}
}
func strPtr(str string) *string {
// 返回 string 的指针
return &str
}
四、循环与条件判断
1.循环
1.1 for循环
for循环是go语言唯一能使用的循环语句,其它语言还会存在 while 循环...
func main() {
// for循环
for i := 0; i < 5; i++ {
fmt.Println(i)
}
}
1.2break语句
结束当前整个for循环,多个for循环时便是结束当前for循环代码块
func main() {
// for循环
for i := 0; i < 5; i++ {
fmt.Println("i:", i)
// break结束循环
if i == 2 {
break
}
}
}
1.3continue语句
仅跳过本次循环,继续下次循环
func main() {
// for循环
for i := 0; i < 5; i++ {
// continue跳过当前循环,继续下次循环
if i == 1 {
fmt.Println("continue进入下次循环,不在执行下面代码")
continue
}
}
}
完整代码:
package main
import "fmt"
func main() {
// for循环
for i := 0; i < 5; i++ {
// 仅跳过本次循环,继续下次循环
if i == 1 {
fmt.Println("continue进入下次循环,不在执行下面代码")
continue
}
fmt.Println("i:", i)
// break结束循环
if i == 2 {
break
}
for j := 0; j < 5; j++ {
if j == 0 {
fmt.Println("跳出嵌套的for循环代码块")
break
}
fmt.Println("被上面break,下面条件永远不可能满足...")
}
}
}
2.条件判断
if是一个具有布尔条件的语句,如果该条件为真,则执行第一个代码块。如果条件求值为false,则执行另一个else块。
1.条件判断 if else
// 条件判断 if else
age := 18
if age >= 18 { // age >=18 为条件
fmt.Println("age is >= 18")
} else {
fmt.Println("age is < 18")
}
2.且与或
- &&:且,需要同时满足条件
- ||:或,满足其中一个条件即可
age := 18
// &&:且,需要同时满足条件
if age > 16 && age < 20 {
fmt.Println("ge > 16 且 age < 20, result age is:", age)
} else if age > 22 {
fmt.Println("age is >22")
} else {
fmt.Println("age is <16 or > 22")
}
// ||:或,满足其中一个条件即可
if age > 20 || age == 18 {
fmt.Println("age is >20 or ==18")
}
3.switch条件语句
1)switch条件语句,匹配后默认break(可写多个条件)
// switch条件语句,匹配后默认break(可写多个条件)
number := 18
switch number {
case 12, 13:
fmt.Println("The is 12, 13")
case 18:
fmt.Println("The is 18")
default:
fmt.Println("The is default")
}
2)switch还可以使用类似 if else
// switch还可以使用类似 if else
switch {
case number >= 16 && number <= 25:
fmt.Println("The is >=16 and <=25")
default:
fmt.Println("switch default")
}
完整代码:
package main
import "fmt"
func main() {
// 条件判断 if else
age := 18
if age >= 18 { // age >=18 为条件
fmt.Println("age is >= 18")
} else {
fmt.Println("age is < 18")
}
// &&:且,需要同时满足条件
if age > 16 && age < 20 {
fmt.Println("ge > 16 且 age < 20, result age is:", age)
} else if age > 22 {
fmt.Println("age is >22")
} else {
fmt.Println("age is <16 or > 22")
}
// ||:或,满足其中一个条件即可
if age > 20 || age == 18 {
fmt.Println("age is >20 or ==18")
}
// 常用判断满足直接返回值,避免使用else
num := 19
if num%2 == 0 {
fmt.Println(num, "is even")
return
}
fmt.Println(num, "is odd")
// switch条件语句,匹配后默认break(可写多个条件)
number := 18
switch number {
case 12, 13:
fmt.Println("The is 12, 13")
case 18:
fmt.Println("The is 18")
default:
fmt.Println("The is default")
}
// switch还可以使用类似 if else
switch {
case number >= 16 && number <= 25:
fmt.Println("The is >=16 and <=25")
default:
fmt.Println("switch default")
}
checkType(1)
}
func checkType(i interface{}) {
switch v := i.(type) {
case string:
fmt.Println(v, "is string")
case int:
fmt.Println(v, "is int")
default:
fmt.Println(v, "is other")
}
}
End