Go lang Learn Note
标签(空格分隔): Go
Go安装和Go目录
设置环境变量GOROOT
和GOPATH
,前者是go的安装目录,后者是开发工作目录。go get
包只会将包下载到第一个工作目录(多个GOPATH的时候)。
Go语言命令行工具介绍
- go build 用于编译源码文件、代码包、李赖堡
- go run 可以编译并运行go源码文件
- go get 主要是用来动态获取远程代码包
GoLand编辑器选择和配置
一、GO语言基础语法
1. 关键字、标识符
- GO中保留的关键字(25个)
break | default | func | interface | select |
---|---|---|---|---|
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | return | var |
- GO中预定的标识符,包括基础数据类型和系统内嵌函数(36个)
append | bool | byte | cap | close | complex |
---|---|---|---|---|---|
complex64 | complex128 | uint16 | copy | false | float32 |
float64 | imag | int | int8 | int16 | uint32 |
int32 | int64 | iota | len | make | new |
nil | panic | uint64 | printIn | real | |
recover | string | TRUE | uint | uint8 | uintprt |
2. 注释
// 单行注释
/* 多行注释 */
3. 基础结构
// 程序所属包
package main
// 导入依赖包
import "fmt"
// 常量定义
const NAME string = "John"
// 全局变量声明与赋值
var name string = "Bob"
// 一般类型声明
type typeInt int
// 结构声明
type Learn struct { }
// 接口声明
type ILeran interface { }
// 函数定义
func learnFoo() {
fmt.Println("learn foo")
}
// main()函数
func main() {
fmt.Println("simple demo")
fmt.Println(NAME)
fmt.Println(name)
learnFoo()
}
运行结果
simple demo
John
Bob
learn foo
Process finished with exit code 0
4. Package用法
- package是最基本的分发单位和工程管理中依赖关系的体现。
- 每个GO语言源代码文件开头都拥有一个package声明,表示源码文件所属代码包。
- 要生成GO语言可执行程序,必须要有main的package包,且必须在该包下有main()函数。
- 同一个路径下只能存在一个package,一个package可以拆分成多个源文件组成。
- 建议package名称和目录名称一致
- 同一路径下只能有同一个package名
5.1 import用法
- 可以导入源代码文件所依赖的package包。
- 不得导入源代码文件中没有用到的package,否则会编译错误。
- 两种格式:
import "package1"
import "package2"
...
import (
"package1"
"package2"
...
)
导入未使用包,会抛出如下错误:
import-demoimport-demo.go:5:2: imported and not used: "time"
Compilation finished with exit code 2
- 如果一个main导入其它包,包将被顺序导入。
- 如果导入的包中依赖其它包(包B),会首先导入包B,然后初始化包B中的常量和变量,最后如果包B中有init,会自动执行init(),然后回到main中。
- 所有包导入完成后才会对main中常量和变量进行初始化,然后执行main中的init函数,最后执行main函数。
- 如果一个包被导入多次,则该包只会被导入一次。
import-demo.go
package main
import (
"fmt"
"./src/show"
"./src/learn"
)
// 所有依赖包初始化完成后
// 才执行main的初始化函数
func init() {
fmt.Println("import-demo init")
}
func main() {
// learn的init函数只执行了一次
// 可知多次导入只被导入一次
learn.Learn()
show.Show()
fmt.Println("Hello world")
}
show/show.go
package show
import (
"fmt"
"../learn"
)
func init() {
fmt.Println("show init")
}
func Show() {
learn.Learn()
fmt.Println("show func")
}
learn/learn.go
package learn
import "fmt"
func init() {
fmt.Println("learn init")
}
func Learn() {
fmt.Println("learn func")
}
然后我们运行import-demo.go,可见执行结果:
learn init
show init
import-demo init
learn func
learn func
show func
Hello world
Process finished with exit code 0
5.2 import别名
- 将导入的包命名为另一个容易记忆的别名。
- 点(.)标识的包导入后,调用改包中的函数时可以省略前缀包名。
- 下划线(_)表示导入该包,但不导入整个包,而是执行该包中的init函数,因此无法通过包名来调用包中的其它函数。使用下划线操作往往是为了注册包里的引擎,让外部可以方便的使用。
别名
import (
myFmt "fmt"
)
6 数据类型
数据类型的出现主要是为了把数据分成所需内存大小不同的数据,可以充分利用内存。
布尔型只可以是true或者false。
字符串类型编码统一为UTF-8。
6.1 整型
类型 | 描述 |
---|---|
uint8 | 无符号 8 位整型 (0 到 255) |
uint16 | 无符号 16 位整型 (0 到 65535) |
uint32 | 无符号 32 位整型 (0 到 4294967295) |
uint64 | 无符号 64 位整型 (0 到 18446744073709551615) |
int8 | 有符号 8 位整型 (-128 到 127) |
int16 | 有符号 16 位整型 (-32768 到 32767) |
int32 | 有符号 32 位整型 (-2147483648 到 2147483647) |
int64 | 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807) |
6.2 浮点型
类型 | 描述 |
---|---|
float32 | IEEE-754 32位浮点型数 |
float64 | IEEE-754 64位浮点型数 |
complex64 | 32位实数和虚数 |
complex128 | 64位实数和虚数 |
6.3 其他数字类型
类型 | 描述 |
---|---|
byte | 类似 uint8 |
rune | 类似 int32 |
uint | 32或64位 |
int | 与uint一样大小 |
uintptr | 无符号整型 用于存放一个指针 |
package main
import (
"fmt"
"unsafe"
)
func main() {
// var i uint8 = 1 // 1
// var i uint32 = 1 // 4
var i uint = 1 // 8
fmt.Println(unsafe.Sizeof(i))
var j float32 = 1 // 4
fmt.Println(unsafe.Sizeof(j))
var b bool = true
fmt.Println(b)
var bt byte = 1 // 1 类似 uint8
fmt.Println(unsafe.Sizeof(bt))
var r rune = 1 // 4 类似 int32
fmt.Println(unsafe.Sizeof(r))
}
6.4 派生类型
6.5 类型零值和类型别名
类型零值不是空值,是被声明后的默认值。值类型默认值为0,布尔型默认值为false,string默认值为空字符串
package main
import (
"fmt"
"reflect"
"unsafe"
)
type 别名 int32
func main() {
var i int32
var j float32
var b bool
var d complex64
var s string
fmt.Print("int32: ")
fmt.Println(i) // int32: 0
fmt.Print("float32: ")
fmt.Println(j) // float32: 0
fmt.Print("bool: ")
fmt.Println(b) // bool: false
fmt.Print("complex64: ")
fmt.Println(d) // complex64: (0+0i)
fmt.Print("string: ")
fmt.Println(s) // string:
var i_b 别名
var i_n int32
fmt.Print("i_b 别名 默认值: ")
fmt.Print(i_b) // 别名: 0
fmt.Print(", i_b 别名 数据类型: ")
fmt.Print(reflect.TypeOf(i_b))
fmt.Print(", i_b 别名 占用大小: ")
fmt.Println(unsafe.Sizeof(i_b))
// Result: i_b 别名 默认值: 0, i_b 别名 数据类型: main.别名, i_b 别名 占用大小: 4
fmt.Print("i_n int32 默认值: ")
fmt.Print(i_n) // 别名: 0
fmt.Print(", i_n int32 数据类型: ")
fmt.Print(reflect.TypeOf(i_n))
fmt.Print(", i_n int32 占用大小: ")
fmt.Println(unsafe.Sizeof(i_n))
// Result: i_n int32 默认值: 0, i_n int32 数据类型: int32, i_n int32 占用大小: 4
// 不同类型不能运算, 包括别名
}
6.6 类型存储大小
7 变量与常量
7.1 变量声明 初始化与赋值
- 变量声明和赋值
变量声明: var [变量名称] <变量类型>
变量赋值: [变量名称] = [值]
声明与赋值同时进行: var [变量名称] <变量类型> = [值]
分组声明:
var (
i int
j float32
name string = "abc"
)
同一行声明多个变量和赋值: var a, b, c int = 1,2,3
或者a, b := 1,2
全局变量的声明必须使用var关键字,局部变量可以省略
特殊变量下划线 _
package main
import (
"fmt"
"reflect"
)
// 全局变量var是必须的
var a int
var b string = "abc"
// 分组方式
var (
c string
d int
e string = "小明"
)
func main() {
fmt.Println(a) // 0
a = 123 // 赋值
fmt.Println(a) // 123
fmt.Println(b) // abc
fmt.Print("c: ")
fmt.Print(c)
fmt.Print(", d: ")
fmt.Print(d)
fmt.Print(", e: ")
fmt.Println(e)
// c: , d: 0, e: 小明
var f, g, h int = 1, 2, 3
fmt.Print("f: ")
fmt.Print(f)
fmt.Print(", g: ")
fmt.Print(g)
fmt.Print(", h: ")
fmt.Println(h)
// f: 1, g: 2, h: 3
var i, j, k = 11, 21.3, 31
fmt.Print("i: ")
fmt.Print(i)
fmt.Print("i 数据类型为: ")
fmt.Print(reflect.TypeOf(i))
fmt.Print(", j: ")
fmt.Print(j)
fmt.Print(", j 数据类型为: ")
fmt.Print(reflect.TypeOf(j))
fmt.Print(", k: ")
fmt.Println(k)
// i: 11i 数据类型为: int, j: 21.3, j 数据类型为: float64, k: 31
// 冒号简写,只能在函数体内使用
l, m, n := 11, 21.3, "c"
fmt.Print("l: ")
fmt.Print(l)
fmt.Print(", m: ")
fmt.Print(m)
fmt.Print(", n: ")
fmt.Println(n)
// l: 11, m: 21.3, n: c
// 下划线
var o, _, p = 11, 21.3, 31
fmt.Print("o: ")
fmt.Print(o)
fmt.Print(", p: ")
fmt.Print(p)
// fmt.Print(", _: ")
// fmt.Println(_) // 下划线不能被打印
// o: 11, p: 31
}
7.2 变量类型转换
不能隐式转换,必须显式
类型转换只能发生在两种兼容类型之间
类型转换格式: [变量名称] [:]= <目标类型>([需要转换的变量名称])
package main
import (
"fmt"
"reflect"
)
func main() {
var a int = 1
var b float32 = 2.3
c := float32(a)
fmt.Print(c)
fmt.Print(" ")
fmt.Println(reflect.TypeOf(c))
d := int32(b)
fmt.Print(d)
fmt.Print(" ")
fmt.Println(reflect.TypeOf(d))
}
7.3 变量可见性规则
大写字母开头的变量是可导出的,是公用变量
小写字母开头的变量是私有变量,不可导出被读取
package B
// 大写字母开头的变量是可导出的,是公用变量
// 小写字母开头的变量是私有变量,不可导出被读取
var a = "变量a"
var A = "变量A"
package main
import (
"fmt"
"./B"
)
func main() {
fmt.Println(B.A) // 变量A
}
7.4 常量
- 定义形式 类型范围
显示: const identifier <type> = value
隐式: const identifier = value
,无类型常量
常量可以使用内置表达式定义,len()
unsafe.Sizeof()
只支持布尔型、数字型(整数型、浮点型和复数)、字符串型
常量不能使用 :=
语法定义。
package main
import "fmt"
const a string = "常量a" // 显式
const b = "常量b" // 隐式
const (
c string = "常量c"
d = "常量d"
)
const e, _, f = "常量e", "下划线", 6
const g = len(a) // 只支持内置函数
func main() {
fmt.Println(a) // 常量a
fmt.Println(b) // 常量b
fmt.Println(c) // 常量c
fmt.Println(d) // 常量d
fmt.Println(e) // 常量e
fmt.Println(f) // 6
fmt.Println(g) // 7
}
- iota的使用
在const关键字出现时将被重置为0
const中每新增一行常量声明将使iota +1
跳值使用法、插队使用法、表达式隐式使用法、单行使用法
package main
import "fmt"
func main() {
// 在const关键字出现时将被重置为0
const h = iota
const i = iota
fmt.Print("h值为: ")
fmt.Print(h)
fmt.Print(", i值为: ")
fmt.Println(i)
// h值为: 0, i值为: 0
// const中每新增一行常量声明将使iota +1
const (
j = iota
k = iota
)
fmt.Print("j值为: ")
fmt.Print(j)
fmt.Print(", k值为: ")
fmt.Println(k)
// j值为: 0, k值为: 1
// 跳值使用法
const (
l = iota
m = iota
_
n = iota
)
fmt.Print("l值为: ")
fmt.Print(l)
fmt.Print(", m值为: ")
fmt.Print(m)
fmt.Print(", n值为: ")
fmt.Println(n)
// l值为: 0, m值为: 1, n值为: 3
// 插队使用法
const (
o = iota
p = 3.14
q = iota
)
fmt.Print("o值为: ")
fmt.Print(o)
fmt.Print(", p值为: ")
fmt.Print(p)
fmt.Print(", q值为: ")
fmt.Println(q)
// o值为: 0, p值为: 3.14, q值为: 2
// 表达式隐式使用法
// 自动向上使用非空表达式
const (
r = iota * 2
s = iota * 3
t
u
)
fmt.Print("r值为: ")
fmt.Print(r)
fmt.Print(", s值为: ")
fmt.Print(s)
fmt.Print(", t值为: ")
fmt.Print(t)
fmt.Print(", u值为: ")
fmt.Println(u)
// r值为: 0, s值为: 3, t值为: 6, u值为: 9
const (
aa, bb = iota, iota + 3
cc, dd
ee = iota
)
fmt.Print("aa值为: ")
fmt.Print(aa)
fmt.Print(", bb值为: ")
fmt.Print(bb)
fmt.Print(", cc值为: ")
fmt.Print(cc)
fmt.Print(", dd值为: ")
fmt.Print(dd)
fmt.Print(", ee值为: ")
fmt.Println(ee)
// aa值为: 0, bb值为: 3, cc值为: 1, dd值为: 4, ee值为: 2
}
8.运算符
8.1 算数运算符
+
, -
, *
, /
, %
, ++
, --
++
, --
只能在变量后面用。
8.2 关系运算符
==
, !=
, >
, >=
, <
, <=
8.3 逻辑运算符
&&
, ||
, !
8.3 按位运算符
&
按位与 两者都为1则结果为1|
按位或 有一个为1 结果为1^
按位异或 对应位 不同数值时结果为1,相同数值为0<<
左移 把数整体向左移动>>
右移 把数整体向右移动
package main
import "fmt"
func main() {
a := byte(0)
b := byte(1)
fmt.Print("a 的值为: ")
fmt.Println(a)
fmt.Print("b 的值为: ")
fmt.Println(b)
fmt.Println("")
fmt.Print("a&b 的值为: ")
fmt.Println(a&b)
fmt.Print("a|b 的值为: ")
fmt.Println(a|b)
fmt.Print("a^b 的值为: ")
fmt.Println(a^b)
fmt.Print("a^a 的值为: ")
fmt.Println(a^a)
fmt.Print("b << 1 的值为: ")
fmt.Println(b << 1)
fmt.Print("b >> 1 的值为: ")
fmt.Println(b >>1 )
}
a 的值为: 0
b 的值为: 1
a&b 的值为: 0
a|b 的值为: 1
a^b 的值为: 1
a^a 的值为: 0
b << 1 的值为: 2
b >> 1 的值为: 0
Process finished with exit code 0
8.4 赋值运算符
=
赋值+=
加等-=
减等*=
乘等/=
除等%=
余等 a %= 2 相当于 a = a % 2<<=
左移后赋值 a <<= 2 相当于 a = a << 2>>=
右移后赋值 a >>= 2 相当于 a = a >> 2&=
按位与后赋值 a &= 2 相当于 a = a & 2^=
按位异后赋值 a ^= 2 相当于 a = a ^ 2|=
按位或后赋值 a |= 2 相当于 a = a | 2
9 控制语句
9.1 if else
9.2 switch, select
9.3 for
// for 循环
for i := 1; i <= 10; i++ {
fmt.Println(i)
time.Sleep(1 * time.Second)
}
// forEach 循环
b := []string{"字符串1", "字符串2", "字符串3", "字符串4", "字符串5"}
for key, value := range b {
fmt.Print("key的值为: ")
fmt.Println(key)
fmt.Print("value的值为: ")
fmt.Println(value)
}
9.4 goto, break, continue
goto
跳转到指定流程break
跳出循环continue
跳出本次循环
// goto
goto One
fmt.Println("代码块1")
fmt.Println("代码块2")
One:
fmt.Println("代码块One")
fmt.Println("代码块Two")
// break
for i := 1; i <= 3; i++ {
for j := 0; j < 3; j++ {
fmt.Print("循环体-")
fmt.Print(i)
fmt.Print("-")
fmt.Println(j)
break
}
}
// continue
for i := 0; i < 3; i++ {
if i > 1 {
fmt.Println("满足i > 1, continue, 跳出本次循环")
continue
}
fmt.Print("当前下标为: ")
fmt.Println(i)
}
Last updated by Jehorn, Aug 16 2018