golang base (one)
程序入口
必须为
package main
必须是
func main(){}
文件名称可以不为
main.go
Go
中main
函数不支持返回值可以通过
os.Exit()
来传出 返回值main
函数不支持传入参数 可以通过os.Args
来获取1
2
3
4
5
6
7
8
9
10func main(){// 不支持入参
fmt.Println("hello world!")
if len(os.Args) >1 {//通过 os.Args 来获取传入的参数
for arg,value := range os.Args{
fmt.Println(arg,value)
}
}
os.Exit(0)
}
变量,常量以及与其它语言的区别
编写测试程序
源码文件以
_test
结尾:xxx_test.go
测试方法名以
Test
开头TestXXX(t *testing.T){...}
go test -v xxx_test.go
才能输出t.Log
里的文字实现斐波拉契数列
1
2
3
4
5
6
7func TestFibList(t *testing.T) {
a,b := 1,1
for i := 0; i < 5; i++ {
fmt.Println(b)
a,b = b,a+b
}
}
变量与其它静态编程语言的差异
- 赋值可以进行自动类型推断
- 同一个赋值语句中可以对多个变量进行同时赋值
常量与其它静态编程语言的差异
快速设置连续值
iota
遇到下一个const
之前连续递增1,遇到之后变为0iota
只能在常量中使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33const (
Monday = iota + 1 // 1
Tuesday // 2
Wednesday // 3
)
const (
Readable = 1 << iota //1 0001
Writable //2 0010
Executable //4 0100
)
const (
i = iota // i=0
j = 3.14 // j=3.14
k = iota // k=2
l // l=3
)
type ByteSize float64
const (
_ = iota // ignore first value by assigning to blank identifier
KB ByteSize = 1 << (10 * iota) // 1 << (10*1)
MB // 1 << (10*2)
GB // 1 << (10*3)
TB // 1 << (10*4)
PB // 1 << (10*5)
EB // 1 << (10*6)
ZB // 1 << (10*7)
YB // 1 << (10*8)
)
数据类型
- 基本数据类型 值类型 初始化时默认会有零值
bool
:false
string
:""
int int8 int16 int32 int64
:0
uint uint8 uint16 uint32 uint64 uintptr
:0
byte
:0
// alias for uint8rune
:0
// alias for int32,represents a Unicode code pointfloat32 float64
:0
complex64 complex128
:(0+0i)
- 复合类型
pointer function interface slice channel map
:nil
- 对于复合类型,
go
语言会自动递归地将每一个元素初始化为其类型对应的零值。比如:数组, 结构体
整型占用字节问题
int,uint整型:和机器平台有关,最小32位,占用4字节,64位,占用8字节。
1
2
3
4
5
6//机器位数
cpu := runtime.GOARCH
t.Log(cpu) // amd64
//int占用位数
int_size := strconv.IntSize
t.Log(int_size) // 64
数值范围
类型 | 长度(字节) | 数值范围 |
---|---|---|
int8 | 1 | -128~127 (-2^(8-1) ~ 2^7-1) |
uint8 | 1 | 0~255 (0 ~ 2^8-1) |
int16 | 2 | -32768~32767 |
uint16 | 2 | 0~65535 |
int32 | 4 | -2^31 ~ 2^31-1 (-2147483648~2147483647) |
uint32 | 4 | 0 |
int64 | 8 | -2^63 ~2^63-1 |
uint64 | 8 | 0~2^63 |
数据类型与其它静态编程语言的差异
Go语言不允许隐式类型转换
别名和原有类型也不能进行隐式类型转换
- 在某些语言中允许小范围类型向大范围类型转换,因为数据精度不会丢失
- 大范围向小范围转换会导致精度丢失
1
2
3
4
5
6
7
8
9type MyInt int64
func TestDataType(t *testing.T){
var a int32 = 1
var b int64
b = int64(a)
var c MyInt
c = MyInt(b)
t.Log(a,b,c)
}Go
语言不支持指针运算string
是值类型,其默认的初始值为""
空字符串,而不是nil
1
2
3
4
5
6
7
8
9
10
11
12func TestPoint(t *testing.T) {
a := 1
aPtr := &a
// aPtr = aPtr + 1 是不被允许的
t.Log(a, aPtr)// 1 0xc00000a2b8
t.Logf("%T %T", a, aPtr)// int *int
var s string
if s == "" {
t.Log("string 零值为空字符串")
}
t.Log(len(s)) //0
}
运算符号与其它静态编程语言的差异
算术运算符
+ - * / % 后++ 后--
比较运算符
==
!=
>
<
>=
<=
在
golang
比较数组 如果两个数组的维度相等是可以比较的1
2
3
4
5a :=[...]int{1,2,3,4} // 数组声明
b :=[...]int{1,2,4,3}
c :=[...]int{1,2,3,4}
t.Log(a == b) // false
t.Log(a == c) // true
逻辑运算符
!
&&
||
位运算符号
&
按位与(A & B) 结果为12 二进制为00001100|
按位或(A|B)结果为61,二进制为00111101^
按位异或(A^B)结果为49,二进制为00110001<<
A << 2 结果为240 ,二进制为11110000>>
A >> 2 结果为15 ,二进制为00001111&^
按位清零 运算符 右边为1 则左边清零 为0则左边为原值1
2
3
41 &^ 0 --> 1 // 右边为0 则左边不变
1 &^ 1 --> 0 // 右边为1 则左边清零
0 &^ 1 --> 0 // 右边为1 则左边清零
0 &^ 0 --> 1 // 右边为0 则左边不变
第八讲 流程控制
只有 for
一个关键字
for
不需要前后的括号
1 |
|
if
条件
- 只有结果为
bool
值,才能成为if
的条件
1 |
|
switch
条件
条件表达式 不限制为常量或者整数
单个case中,可以出现多个结果选项,用逗号分隔
与 C 语言规则相反, Go 不需要加上break 来明确推出一个case
可以不设定 swtich 之后的条件表达式,在此种情况下,整个 switch 结构与多个 if…else… 的逻辑作用相同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20for i := 0; i < 5; i++ {
switch i {
case 0, 2:
t.Log("Even")
case 1, 3:
t.Log("Odd")
default:
t.Log("it is not 0-3")
}
}
for i := 0; i < 5; i++ {
switch {
case i%2 == 0:
t.Log("Even")
case i%2 != 0:
t.Log("Odd")
default:
t.Log("unKnow")
}
}
第九讲 数组与切片
数组
- 数组的声明
1 |
|
- 数组与
slice
的循环
1 |
|
- 数组与slice 的截取
1 |
|
切片
1 |
|
区别
容量是否可伸缩
- 切片容量可伸缩
- 首先判断,如果新申请容量(cap)大于2倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)
- 否则判断,如果旧切片的长度小于1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap)
- 否则判断,如果旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的 1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)
- 如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)
- slice的共享内存存在一个隐患,就是使用共享内存的双方slice如果有一方出现扩容,则扩容一方将不再指向原有空间。所以程序中想以修改一方达到数据同步时需要小心
- 扩容后会指向一个更大的空间,不再指向原有空间,所以共享内存失效
- 数组声明后长度不可修改
- 切片容量可伸缩
是否可比较
- 数组可以比较 同一类型 同一长度的数组可以比较
- slice 只能与 nil 进行比较