这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
数据类型
string是基础类型
int float32 float64 string bool 等
变量/常量
- 变量有两种声明方法:
var和:=, 支持类型自动推导(需给出初始值)
var a = 1
var b int = 2
var c // 错误, 没有类型初值,无法推导
d := 1
e := float32(d)
f += "aaa" + "bbb" // 字符串支持直接拼接
- 常量,把
var替换为const来声明常量
const a = 1
const b string = "ccc"
const c int = 123
分支/循环
- if分支:
if后面的bool表达式没有括号,并且必须将后面的语句包含在换行的大括号里。
if 7 % 2 == 0 {
// stmt here
}
if 8 % 4 == 0 {
// stmt
} else {
// stmt
}
// if语句的最后一块是bool即可,之前可以放任何语句,用逗号隔开
if num := 9; num > 0 {
// stmt
} else if num < 0 {
// stmt
}
- switch分支:case后自动break
a := 2
switch a {
case 1:
//
case 2:
//
default:
//
}
- for循环:go中的
for循环可以实现loop,while,for i,for k, v等
// loop
for {
fmt.Println("loop")
}
// while
i := 1
for i <= 3 {
i = i + 1
}
// for i
for j := 1; j < 10; j ++ {
fmt.Println(j)
}
// for k, v?
数组/切片
- 数组使用
[N]int,[N][N]string来声明数组
var a [5]int
a[4] = 100
fmt.Println(a[4], len(a)) // 100 5
b := [5]int{1, 2, 3, 4, 5}
fmt.Println(b) // [1 2 3 4 5]
var c [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
c[i][j] = i + j
}
}
fmt.Println(b) // [[0 1 2] [1 2 3]]
- 切片使用
make([]int, capacity)来创建,capacity是切片的初始容量,切片可以使用append()扩充容量
a := make([]int, 3)
a[0] = 1
a[1] = 2
a[2] = 3
fmt.Println(a[1], len(a)) // 2 3
// append()由于会扩充容量,即重新分配容量,需要将切片传进去,并赋值会切片
a = append(a, 4) // 插入值
a = append(a, 5, 6) // 插入两个值
fmt.Println(a) // [1 2 3 4 5 6]
b := make([]int, 6)
copy(b, a) // 将a中的值复制给b
切片操作:大体同Python,但不支持负数下标来倒序访问
// 下标2 -> 5 - 1
fmt.Println(b[2:5]) // [3 4 5]
// 下标0 -> 5 - 1
fmt.Println(b[:5]) // [1 2 3 4 5]
// 下标2 -> len() - 1
fmt.Println(b[2:]) // [3 4 5 6]
哈希表
使用make(map[string]int)来创建哈希表,同C++里的unordered_map<string, int>
mp := make(map[string]int)
mp["a"] = 1
mp["b"] = 2
// 或者mp := map[string]int{"a":1, "b":2}
fmt.Println(mp) // map[a:1 b:2]
fmt.Println(len(mp)) // 2
fmt.Println(mp["a"]) // 1
delete(mp, "b") // 删除键
对于无效键,默认返回值的零值
fmt.Println(mp["unset"]) // 0
// 也可以这样来判断
x, ok := mp["unset"] // x == 0, ok == false
范围
range关键字,可以用于快速遍历切片、哈希表等。如果不需要用到某个值,可以用_来忽略
遍历切片
nums := []int{1, 2, 3}
for i, v := range nums {
fmt.Println("index:", i, "val:", v)
}
for _, v := range nums {
fmt.Println("val:", v)
}
遍历哈希表
mp := map[int]int{1:1000, 2:2000, 3:3000}
for k, v := range mp {
fmt.Println("key:", k, "val:", v)
}
for _, v := range mp {
fmt.Println("val:", v)
}
函数
go中的函数支持返回多个值
func a() int {
// 返回int
return 1
}
func b() (x int, ok bool) {
x = 2 // x和ok已在上面定义
ok = true
return x, ok
// 语法糖:直接return,就可以返回定义的返回值了
}
func main() {
aa := a()
bb, ok := b()
fmt.Println(aa, bb, ok) // 1 2 true
}
指针
函数可以处理传入的变量指针
func addPtr(x *int) {
*x += 2
}
func main() {
a := 1
addPtr(&a)
fmt.Println(a) // 3
}
结构体
go中没有类,仅有结构体
type node struct {
a int
b int
}
func cmpA(n node, x int) bool {
return n.a == x
}
func mod(n *node, x int) {
n.a = x // 指针修改结构体的值无需解引用
}
func main() {
// 定义结构体
a := node{a: 1, b: 2}
// b := node{2, 3}
// c := node{b: 3} // 定义部分值
// var d node
// d.a = 1
// d.b = 2
fmt.Println(a) // {1 2}
fmt.Println(cmpA(a, 2)) // false
mod(&a, 2)
fmt.Println(cmpA(a, 2)) // true
}
结构体方法就类似类中的成员函数
type node struct {
a int
b int
}
func (n node) cmpA(x int) bool {
return n.a == x
}
func (n *node) mod(x int) {
n.a = x
}
异常处理
go使用error类型的返回值抛出异常,使用if来处理异常
func (n *node) mod(x int) (err error) {
if n.a == 0 {
return errors.New("no a value")
} else {
n.a = x
}
return
}
func main() {
a := node{b: 2}
// exception handler
if err := a.mod(1); err != nil {
fmt.Println(err) // nil struct
return
}
fmt.Println(a.a) // never print
}
JSON处理
go中的encoding/json包可以很方便的序列化结构体和反序列化JSON
type node struct {
Name string
Age int `json:"age"` // key Age -> age
}
func (n *node) Serialize() ([]byte, error) {
buf, err := json.Marshal(n) // 序列化
if err != nil {
return nil, err
}
return buf, nil
}
func (n *node) Deserialize(buf []byte) error {
err := json.Unmarshal(buf, &n) // 反序列化
if err != nil {
return err
}
return nil
}
func main() {
n := &node{
Name: "John",
Age: 30,
}
buf, err := n.Serialize()
if err != nil {
panic(err)
}
// []byte切片,直接打印是数字,需要类型转换
fmt.Println(string(buf)) // {"Name":"John","age":30}
var n2 node
err = n2.Deserialize(buf)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", n2) // main.node{Name:"John", Age:30}
}