# 基础
# 一. 变量赋值
# 默认值
- int 变量默认为
0
- string 变量默认为
""
package main
import "fmt"
func variableZeroValue() {
var a int
var s string
// Println 只能跟名字
fmt.Println(a, s)
// Printf 可以跟格式
fmt.Printf("%d %q\n", a, s) // 0, ""
}
func main() {
variableZeroValue()
}
# 变量赋值
package main
import "fmt"
func variableInitialValue() {
var a, b int = 3, 4
var s string = "abc"
fmt.Println(a, b, s)
}
func main() {
variableInitialValue()
}
# 简略写法
package main
import "fmt"
// 外部声明必须使用 var
var aa = 1
var (
bb = "bb"
cc = "cc"
)
func variableShortValue() {
// 只能在 func 里面使用 := , 在函数外面必须使用 var 声明
a, b int := 3, 4
b = 5;
fmt.Println(a, b)
}
func main() {
variableShortValue()
}
# 枚举类型
package main
import "fmt"
func enums() {
// iota 表示自增, 从1开始自增
// 下划线表示跳过
const (
cpp = iota
_
java
python
golang
)
fmt.Println(cpp, java, python, golang)
}
func main() {
enums()
}
# 二. 基本数据类型
bool
string
int
int8
int16
int32
int64
uint
uint8
uint32
uint64
uintptr(指针)
(无符号)byte 字符型长度8
rune 字符型长度32
float32
float64
complex64
complex128
(复数)
提示
没有 char
类型,只有 rune
# 三. 类型转化
- Go 语言不允许隐式类型转换
- 别名和原有类型也不能进行隐式类型转换
例如:
package try_test
import (
"testing"
)
type MyInt int64
func TestImplicit(t *testing.T) {
var a int32 = 1
var b int64
b = int64(a)
var c MyInt
c = b //这种也是不可以的, 必须显示声明
c = Myint(b) //这种是可以的
}
# 四. 类型的预定义值
# 不支持指针运算
func TestPoint(t *testing.T) {
a := 1
aPtr := &a
aPtr = aPtr + 1 //go不允许指针运算
t.Logf("%T %T", a, aPtr) // int, *int
}
# string 是值类型, 其默认的初始化值为空字符串, 而不是 nil
# 五. 算数运算符
+
相加-
相减*
相乘/
相除%
求余++
自增--
自减
# 六. 比较运算符
==
检测两个值是否相等!=
检测两个值是否不相等>
大于<
小于>=
大于等于<=
小于等于
数组比较
数组比较跟 JavaScript 不一样, go 数组会对数组内部元素进行比较, 如果内部元素相等, 就认为相等
# 七. 逻辑运算符
&&
||
!
# 八. 位运算符
&
|
^
<<
>>
# 九. 循环
# 仅支持 for 关键字
// 循环
// for 初始值; 终止条件; 递归条件
for i := 0; i <= 9; i++ {
...
}
# 无限循环
// 没有 while(true) {} 关键字
for {
...
}
示例:进制转换
package main
import (
"strconv"
"fmt"
)
func convertToBin(n int) string {
result := ""
for ; n > 0; n /= 2 {
lsb := n % 2
// strconv.Iota: 转成字符串
result = strconv.Itoa(lsb) + result
}
return result
}
func main() {
fmt.Println(
convertToBin(5),
convertToBin(10),
)
}
# 十. 判断
- condition 表达式结果必须为布尔值
- 支持变量赋值:
// 支持多段, 第一个语句是赋值, 第二个语句是条件
if var declaration; condition {
// code...
}
例如:读取 abc.txt 文件,如果失败则打印失败信息。如果成功打印内容
// 业务场景
// 通过执行某个函数对变量赋值, 如果出错走到else
package main
import (
"fmt"
"io/ioutil"
)
func main() {
const filename = "abc.txt"
if contents, err := ioutil.ReadFile(filename); err != nil {
fmt.Println(err)
} else {
fmt.Printf("%s\n", contents)
}
}
# 十一. switch 条件
- 条件表达式不限制为常量或者整数;
- 单个 case 中, 可以出现多个结果选项, 使用逗号分隔;
- 与 C 语言等规则相反, Go 语言不需要用 break 来明确退出一个 case;
- 可以不设定 switch 之后的条件表达式, 在这种情况下, 整个 switch 结构与多个 if...else...的逻辑作用等同
// 相当于if else这种也是可以的
switch {
case 0 <= Num && Num <= 3:
fmt.Printf("0-3")
// break 默认有break会执行
case 4 <= Num && Num <= 6:
fmt.Printf("4-6")
case 7 <= Num && Num <= 9:
fmt.Printf("7-9")
}
// case多个值, 这种也是可以的
switch i {
case 0, 2:
t.Log("case 0 or 2")
// break 默认有break会执行
default:
t.Log("default")
}
# 十二. 数组
# 数组的声明
// 声明一个数组, 内部是3个int类型的元素
var arr [3]int
// 或者
arr := [3]int{1, 2, 3, 4}
// 也可以不显示的声明个数
arr := [...]int{1, 3, 4, 5}
// 多维数组
var grid [4][5]int
# 数组的遍历
- (1) 常规 for
for i:=0; i<len(arr3); i++ {
}
- (2) range
for idx, v := range arr {
...
}
// 如果不需要idx, 要用 "_" 占位
for _, v := range arr {
...
}
# 截取
- a[开始索引(包含), 结束索引(不包含)]
func TestArraySection(t *testing.T) {
a := [...]int{1, 2, 3, 4, 5}
t.Log(a[1:2]) // 2
t.Log(a[1:]) // 2, 3, 4, 5
t.Log(a[1:len(a)]) // 2, 3, 4, 5
t.Log(a[:3]) // 1, 2, 3
t.Log(a[:]) // 1, 2, 3, 4, 5
}
WARNING
go 不支持负数索引, 例如 a[-1:]
b[0:-1]
都不可以
# 切片(slice)
(1) 声明
// 切片不声明长度
var s0 []int
(2) 添加元素
s0 = append(s0, 1);
(3) 初始化
s1 := []int{1, 2, 3, 4}
(4) 使用 make 声明切片
- make(切片, 可访问长度, 容量)
s2 := make([]int, 3, 5)
# 切片内部结构
- 指针 ptr 指向数组
- len: 元素的个数
- cap: 内部数组的容量
WARNING
(1) 容量随着 append 填充元素可动态伸缩, 并不是跟长度一致, 而是指数级伸缩, 长度扩展量为 1,2,4,8,16...
(2) 不可以进行比较
// 下面的示例会报错, 两个切片是不允许比较的
func TestSliceComparing(t *testing.T) {
a := []int{1, 2, 3, 4}
b := []int{1, 2, 3, 4}
if a == b {
t.Log("equal")
}
}
← 实现 Fibonacci 数列 Map →