这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天
一、本堂课重点内容:
Go语言基础语法
##示例1-hello world
package main //main包:程式的入口包
import (
"fmt"
) //fmt包:输入输出字符串、格式化字符串
func main() {
fmt.Println("hello world")
}
二、详细知识点介绍:
##变量类型
整数 浮点型 bool型 字符串等
字符串为内置类型-可通过+拼接
g := a + "foo"
##变量声明
自动推导变量类型-法1
var name = value
或显式写出变量类型-法2
var a int = 2
法3
变量名 := 值
f := float32(e)
常量
const s string = "xxx"//常量没有确定类型,根据使用上下文自动确定
##基础语法-if else
if后无(),判断语句后直接为{},不能写到下一行
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
if 8%4 == 0 {
fmt.Println("8 is divisible by 4")
}
if num := 9; num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
##基础语法-循环-for
i := 1
for {
fmt.Println("loop")
break
}//无跳出条件,死循环
for j := 7; j < 9; j++ {
fmt.Println(j)
}
for n := 0; n < 5; n++ {//可省略任何一段
if n%2 == 0 {
continue//继续循环,break-跳出循环
}
fmt.Println(n)
}
##基础语法-switch
switch后的变量名不需要()
不加break也不会接着跑其他的分支
a := 2
switch a {
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
default:
fmt.Println("other")
}
相比C or C++,golang 中 switch可使用任意的变量类型
e.g.字符串、结构体
也可取代任意的 if else 语句(switch后不加变量,在case后写条件分支)
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
##基础语法-数组
数组的长度是固定的
var a [5]int//定义数组
a[4] = 100 //写入数组中第四个位置的值
fmt.Println("get:", a[2])//得到第三个元素的值:get:0-没有读入值则默认为0
fmt.Println("len:", len(a))//a的长度为5:len:5
b := [5]int{1, 2, 3, 4, 5}
fmt.Println(b)//[1 2 3 4 5]
var twoD [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
twoD[i][j] = i + j
}
}//二维数组用for循环赋值
fmt.Println("2d: ", twoD)//2d: [[0 1 2] [1 2 3]]
##基础语法-切片
1、不同于数组,可任意更改长度,是可以动态变化的数组
2、其使用和数组类似,遍历切片、访问切片的元素和求切片长度len(slice)都一样
3、切片定义的基本语法:
var 切片名 []type = make([]type,len,[cap])//cap,指定切片容量,可选,cap>=len
可用make来创建一个切片
s := make([]string, 3)
s[0] = "a"//向数组一样读入值
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2]) // c
fmt.Println("len:", len(s)) // 3
append-追加元素
s = append(s, "d")//把append的结果赋值给原数组(slice原理实际是它存储了一个长度和一个容量,加一个指向一个数组的指针,在执行append 操作的时候,如果容量不够,会扩容并返回新的slice)
s = append(s, "e", "f")
fmt.Println(s) // [a b c d e f]
copy-拷贝数值
c := make([]string, len(s))
copy(c, s)
fmt.Println(c) // [a b c d e f]
取出元素,顾前不顾尾(s[2:5]"2""5"表下标)
fmt.Println(s[2:5]) // [c d e]
fmt.Println(s[:5]) // [a b c d e]
fmt.Println(s[2:]) // [c d e f]
##基础语法-map
map是key-value数据结构,又称为字段或者关联数组,类似其他编程语言的集合
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
定义Map
可以使用内建函数 make 也可以使用 map 关键字来定义 Map:
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
创建Map,需要两个类型:key和value
m := make(map[string]int)//make,类型推导来定义,创建一个空map
m["one"] = 1//存储键值对
m["two"] = 2
fmt.Println(m) // map[one:1 two:2]
fmt.Println(len(m)) // 2
fmt.Println(m["one"]) // 1
fmt.Println(m["unknow"]) // 0
delete-删除键值对
delete(m, "one")
map查找
/如果map中存在查找的key,ok(可随便定义名称)则返回true,否则false/
r, ok := m["unknow"]//map取key(unknow),返回两个数据:value(r),查找结果(ok)
fmt.Println(r, ok) // 0 false
golang中的map完全无序,遍历的时候不会按照字母顺序或插入顺序输出,而是随机顺序
##基础语法-range
对于一个slice或一个map,可用range快速遍历
遍历时,数组会返回两个值,第一个为索引,第二个为对应位置的值
索引不需要,可用下划线_来忽略
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num) // index: 0 num: 2
}
}
遍历map时第一个值为key,第二个值为value
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v) // b B; a A
}
for k := range m {
fmt.Println("key", k) // key a; key b
}
##基础语法-函数
变量类型后置
func add(a int, b int) int {
return a + b
}
golang中函数原生支持返回多个值,第一个值是真正的返回结构,第二个值是一个错误信息
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
##基础语法-指针
主要用途:对传入参数进行修改
错误示例:
func add2(n int) {
n += 2
}//值拷贝
正确示例:
func add2ptr(n *int) {
*n += 2
}
三、引用参考:
- 文章中Map相关是我参考引用了Go语言Map(集合)-菜鸟教程的