这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
自我总结
了解了Go的基础语法后,相比Java来说更加自由简单,让我有一种Go是一种弱类型语言的错觉,风格还需要慢慢习惯,练习也需要同步。
Go的主要特点
- 高性能,高并发
- 丰富的标准库
- 完善的工具链
- 静态链接
- 快速编译
- 跨平台
- 垃圾回收
语法
变量定义的方式
var a int = 3 // int为可选的
var b := 3
// 常量的定义
const c string = "abc"
const d = 3
if
if判断可以先定义然后判断
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")
}
循环
Go只有
for一种循环
-
死循环
for { ... } -
普通循环
for i := 1; i < 3; i++ { ... }
分支
Go中
switch语句不需要在每个分支后加上break
-
Go的switch强大到可以在一定程度上代替if
t := time.Now() switch { case t.Hour() < 12: fmt.Println("It's before noon") default: fmt.Println("It's after noon") }
切片
在使用append时,必须把append的结果赋值为原数组:因为slice的原理实际上是它存储了一个长度和一个容量,加一个指向数组的指针,在执行append时,如果容量不够会扩容并返回新的slice
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
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s) // [a b c d e f]
c := make([]string, len(s))
copy(c, s)
fmt.Println(c) // [a b c d e f]
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]
good := []string{"g", "o", "o", "d"}
fmt.Println(good) // [g o o d]
map
Go的map是完全无序的,遍历的时候不会按照字母顺序,也不会按照插入顺序输出,而是随机顺序
函数
在实际的业务逻辑函数中几乎所有的函数都返回两个值,第一个是真正的返回结果,第二个值是一个错误信息
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[v]
return v, ok
}
结构体方法
注意带和不带指针的区别
package main
import "fmt"
type user struct {
name string
password string
}
// 这里不使用指针实际上操作的是一个copy
func (u user) checkPassword(password string) bool {
return u.password == password
}
// 这里使用了指针可以直接对结构体进行操作
func (u *user) resetPassword(password string) {
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
fmt.Println(a.checkPassword("2048")) // true
}
错误处理
注意调用函数后处理异常的写法,非常常用
package main
import (
"errors"
"fmt"
)
type user struct {
name string
password string
}
func findUser(users []user, name string) (v *user, err error) {
for _, u := range users {
if u.name == name {
return &u, nil
}
}
return nil, errors.New("not found") // 创建一个异常
}
func main() {
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name) // wang
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err) // not found
return
} else {
fmt.Println(u.name)
}
}
格式化
注意
%v可以匹配任意类型的变量,其中%+v可以打印详细结果,%#v则更加详细
package main
import "fmt"
type point struct {
x, y int
}
func main() {
s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n) // hello 123
fmt.Println(p) // {1 2}
fmt.Printf("s=%v\n", s) // s=hello
fmt.Printf("n=%v\n", n) // n=123
fmt.Printf("p=%v\n", p) // p={1 2}
fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}
f := 3.141592653
fmt.Println(f) // 3.141592653
fmt.Printf("%.2f\n", f) // 3.14
}
数字解析
package main
import (
"fmt"
"strconv"
)
func main() {
f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f) // 1.234
n, _ := strconv.ParseInt("111", 10, 64) // 第二个形参表示进制,10代表十进制,如果传0表示自动推测,64表示返回一个64精度的整数
fmt.Println(n) // 111
n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n) // 4096
n2, _ := strconv.Atoi("123")
fmt.Println(n2) // 123
n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax
}
\