前言
本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。
Go语言的特点
Go语言由Google团队设计,以简洁、高效、并发友好为核心目标。
具有以下优点:
-
语法简单、 学习曲线 平缓:语法关键字很少,且容易记忆。
-
丰富的 标准库:大多数情况下不需要外部引入第三方库,直接使用内置标准库即可。
-
完善的工具链:包管理、代码格式化、测试、性能分析、文档生成、依赖管理等等,应有尽有。
-
静态链接:部署简单,跨平台性强,安全稳定。
-
高性能、高并发:接近c的性能,低内存开销。
下文将介绍Go语言的基本语法,个人感觉更是Go语言现代化(甚至有点超现代化)的体现。
数据类型
Go语言常用的数据类型:
|--------|----------------------|-----------------------------------------------|---------|----------------------------|
| 类型分类 | 类型名称 | 关键字/定义 | 默认值(零值) | 特点 |
| 布尔型 | bool
| bool
| false
| 只能为 true
或 false
|
| 整数型 | 有符号整数 | int
, int8
, int16
, int32
, int64
| 0
| 根据平台不同,int
可能为 32 或 64 位 |
| | 无符号整数 | uint
, uint8
, uint16
, uint32
, uint64
| 0
| 无负数范围 |
| 浮点型 | float32
, float64
| float32
, float64
| 0.0
| float64
精度更高 |
| 字符/字节型 | byte
(别名) | byte
| 0
| uint8
的别名 |
| | rune
(别名) | rune
| 0
| int32
的别名 |
| 字符串型 | string
| string
| ""
| 不可变,UTF-8 编码 |
| 错误类型 | error
| error
| nil
| 内置接口类型,表示错误状态 |
一、变量定义
Go语言的变量定义方式有很多种:
- var name type :用于显式定义变量。
Go
var a, b int = 1, 2
- name := val :用于隐式定义变量。
Go
f := float32(e)
- const name type = val : 用于常量定义
Go
const s string = "constant"
二、选择结构
选择结构分为 if ,switch-case。
- if
Go
if a == 1 {
fmt.Println("真的")
}else {
fmt.Println("假的")
}
- switch-case
Go
a := 2
switch a {
case 1:
fmt.Println(1)
case 2:
fmt.Println(2)
default:
fmt.Println("default")
}
三、循环结构
Go语言形式上只有for循环一种循环方式,但是可以改为类似于while的形式循环。
Go
for i := 1; i < 9; i++ {
fmt.Print(i)
}
k := 1
for k < 10 {
k++
fmt.Println(k)
}
四、数组
Go语言的数组和C很类似,定长数组。
Go
for i := 1; i < 9; i++ {
fmt.Print(i)
}
k := 1
for k < 10 {
k++
fmt.Println(k)
}
五、切片
Go语言的切片类似于C++的vector、Java中的List,是一种变长数组。
并且支持类似Python中元组的操作语法。
Go
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println(s[2])
fmt.Println(len(s))
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s)
c := make([]string, len(s))
copy(c, s)
fmt.Println(c)
fmt.Println(s[2:5])
fmt.Println(s[:4])
fmt.Println(s[2:])
good := []string{"g", "h", "o"}
fmt.Println(good)
六、Map
和各种语言的Map类似,用于存储键值对。
Go
mp := make(map[string]int)
mp["one"] = 1
mp["two"] = 2
r, ok := mp["unknow"]
fmt.Println(r, ok)
七、range
Go语言中的range类似于C++的auto,用于快速遍历。
Go
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("idx:", i, "num:", num)
}
}
fmt.Println(sum)
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v)
}
for k := range m {
fmt.Println(k)
}
八、函数
Go语言的函数,个人认为是Go语言在语法上现代化的标志之一,支持多返回,非常方便。
Go
func add(a int, b int) (int, string) {
return a + b, "ok"
}
九、指针
Go语言的指针类似C的指针,个人非常喜欢指针,一直觉得Java把指针完全去除了也是一个问题。
在语法上,*作为解引用、&作为引用。
Go
func add2(a *int) {
*a += 2
}
十、结构体
Go语言提供结构体用于类型封装,特殊的是,结构体方法在Go语言中需要写在外面。
Go
type user struct {
name string
password string
}
func (this user) checkPassword(password string) bool {
return this.password == password
}
十一、错误处理
Go语言为函数提供了一种新奇的try-catch方法。Go语言中,我们在某种方面来讲是在面向异常编程。我们需要通过 error 类型将函数中的错误返回,然后手动处理。
Go语言提供了一个特殊变量 nil 用于判断是否捕捉到了异常。
Go
func checkError(password string) (bool, error) {
return password == "123", errors.New("not Found")
}
v, err := checkError("456")
if err != nil {
fmt.Println(v, err)
} else {
fmt.Print(v)
}
十二、特殊函数
- json处理
Go
type userInfo struct {
Name string
Age int `json:"age"`
}
func solve14() {
a := userInfo{Name: "wang", Age: 18}
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
fmt.Println(buf)
fmt.Println(string(buf))
var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Println(b)
}
- 时间处理
Go
fmt.Println(time.Now())
fmt.Println(time.Now().Unix())
fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
fmt.Println(time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC))
- 字符串转数字
Go
fmt.Println(strconv.ParseInt("111", 10, 64))
fmt.Println(strconv.ParseFloat("111.11", 64)
fmt.Println(strconv.ParseInt("0x1000", 0, 64
fmt.Println(strconv.Atoi("111"))
- 获取线程信息
Go
fmt.Println(os.Args)
fmt.Println(os.Getenv("PATH"))
下篇将对学习的语法结合视频进行综合实践。