环境按照
略
基础语法
main函数要点
- 无参数、无返回值
- main方法必须要在main包里面
go run main.go
就可以执行- 如果文件不叫
main.go
,则需要go build
之后再go run
包声明
- 语法形式:package xxx
- 字母和下划线的组合
- 可以和文件夹不同名字
- 同一个文件夹下的声明一致
- 引入包语法形式:import [alias] xxx
- 如果一个包引入了但是没有使用,会报错
- 匿名引入:前面多一个下划线
string声明
- 双引号引起来,则内部双引号需要使用
\
转义 引号引起来,则内部
需要\转义
string和基础类型
string长度
- 字节长度:和编码无关,用
len(str)
获取 - 字符数量:和编码无关,用编码库计算
新人入门第一坑:len
统计的是字节,而不是字符。
strings包
- string 的拼接直接使用 + 号就可以。 注意的是,某些语言支持 string 和别的类型拼接, 但是golang 不可以
- strings 主要方法(你所需要的全部都可以找到) :
• 查找和替换
• 大小写转换
• 子字符串相关
• 相等
rune类型
- rune, 直观理解, 就是字符
- rune 不是 byte!
- rune 本质是 int32, 一个 rune 四个字节
- rune 在很多语言里面是没有的, 与之对应的是, golang 没有 char 类型。 rune 不是数字,也不是 char, 也不是 byte!
- 实际中不太常用
bool, int, uint, float 家族
- bool: true, false
- int8, int16, int32, int64, int
- uint8, uint16, uint32, uint64, uint
- float32, float64
byte 类型
- byte, 字节, 本质是 uint8
- 对应的操作包在 bytes 上
类型总结
- golang 的数字类型明确标注了长度、 有无符号
- golang 不会帮你做类型转换, 类型不同无法通过编译。 也因此, string 只能和string 拼接
- golang 有一个很特殊的 rune 类型, 接近一般语言的 char 或者 character 的概念, 非面试情况下, 可以理解为 “ rune = 字符”
- string 遇事不决找 strings 包
变量声明
变量声明 var
• var, 语法: var name type = value
• 局部变量
• 包变量
• 块声明
- 驼峰命名
- 首字符是否大写控制了访问性: 大写包外可访问;
- golang 支持类型推断
变量声明 :=
- 只能用于局部变量, 即方法内部
- golang 使用类型推断来推断类型。 数字会被理解为 int 或者 float64。 (所以要其它类型的数字, 就得用 var 来声明)
变量声明易错点
- 变量声明了没有使用
- 类型不匹配
- 同作用域下, 变量只能声明一次
常量声明 const
- 首字符是否大写控制了访问性: 大写包外可访问;
- 驼峰命名
- 支持类型推断
- 无法修改值
方法声明与调用
方法声明
- 关键字 func
- 方法名字: 首字母是否大写决定了作用域
- 参数列表: [
] - 返回列表: [
]
方法声明(推荐写法)
- 参数列表含有参数名
- 返回值不具有返回值名
方法调用
- 使用 _ 忽略返回值
方法声明与调用总结
- golang 支持多返回值, 这是一个很大的不同点
- golang 方法的作用域和变量作用域一样, 通过大小写控制
- golang 的返回值是可以有名字的, 可以通过给予名字让调用方清楚知道你返回的是什么
数组和切片
数组和别的语言的数组差不多, 语法是: [cap]type
- 初始化要指定长度(或者叫做容量)
- 直接初始化
- arr[i]的形式访问元素
- len 和 cap 操作用于获取数组长度
切片,语法: []type
- 直接初始化
- make初始化:make([]type, length, capacity)
- arr[i] 的形式访问元素
- append 追加元素
- len 获取元素数量
- cap 获取切片容容量
- 推荐写法: s1 := make([]type, 0, capacity)
子切片
数组和切片都可以通过[start:end] 的形式来获取子切片:
- arr[start:end], 获得[start, end)之间的元素
- arr[:end], 获得[0, end) 之间的元素
- arr[start:], 获得[start, len(arr))之间的元素
Tip: 左闭右开原则
如何理解切片
最直观的对比: ArrayList, 即基于数组的 List 的实现, 切片的底层也是数组
跟 ArrayList 的区别:
- 切片操作是有限的, 不支持随机增删(即没有 add, delete 方法, 需要自己写代码)
- 只有 append 操作
- 切片支持子切片操作, 和原本切片是共享底层数组
Tip: 遇事不决用切片, 不容易错
共享底层(optional)
核心: 共享数组
子切片和切片究竟会不会互相影响, 就抓住一点: 它们是不是还共享数组?
什么意思? 就是如果它们结构没有变化, 那肯定是共享的;
但是结构变化了, 就可能不是共享了
有余力的同学可以运行一下 ShareSlice()
for
for 和别的语言差不多, 有三种形式:
- for {} , 类似 while 的无限循环
- for i, 一般的按照下标循环
- for range 最为特殊的 range 遍历
- break 和 continue 和别的语言一样
if - else
带局部变量声明的 if- else:
- distance 只能在 if 块, 或者后边所有的 else 块里面使用
- 脱离了 if - else 块, 则不能再使用
switch
switch 和别的语言差不多
switch 后面可以是基础类型和字符串, 或者满足特定条件的结构体
最大的差别:终于不用加 break 了
Tip: 大多数时候, switch 后面只会用基础类型或者字符串
课后练习
- 计算斐波那契数列
- 实现切片的 Add 和 Delete 方法
- 去 leetcode 上试试(先看答案, 再尝试用 go 写出来) :
- https://leetcode-cn.com/problems/two-sum/
- https://leetcode-cn.com/problems/search-insert-position/
- 我们课上用了很多 fmt 来格式化字符串, 那么如何输出:
- 3.1 保留两位小数的数字
- 3.2 将[]byte 输出为16进制
- 预习 type 的用法
最简单的Web服务器