go语言语法
直接放图Go 程序是通过 package 来组织的。
一个文件夹既是一个包
只有 package 名称为 main 的包可以包含 main 函数。
一个可执行程序有且仅有一个 main 包。
通过 import 关键字来导入其他非 main 包。
可以通过 import 关键字单个导入包名跟文件夹名没啥关系,导入包是文件夹名,也不是文件名
2. 包调用
1. 包调用一般为:项目名/包所在文件层1/.../包所在文件夹
import "workname/packetfolder"
导入多个包
import (
"package1"
"package2"
...
)
方法调用包名.函数//不是函数或结构体所处文件或文件夹名
packagename.Func()
2. 包起别名
package 别名:
// 为fmt起别名为fmt2
import fmt2 "fmt"
3. 省略调用
// 调用的时候只需要Println(),而不需要fmt.Println()
import . "fmt"
前面加个点表示省略调用,那么调用该模块里面的函数,可以不用写模块名称了:
import . "fmt"
func main (){
Println("hello,world")
}
4. import部分调用
当导入一个包时,该包下的文件里所有init()函数都会被执行,然而,有些时候我们并不需要把整个包都导入进来,仅仅是是希望它执行init()函数而已。下划线的作用仅仅是为了调用init()函数,所以无法通过包名来调用包中的其他函数
import _ package
5. 使用go mod导入网络上的包
import "github.com/workname/packagename"
3. 声明
1. 变量声明
变量声明必须要使用否则会报错。
全局变量运行声明但不使用。
var a string = "Runoob"
//也可以
var a = "Runoob"
//一次性声明一种类型的多个变量
var b, c int = 1, 2
//多变量声明
vname1, vname2, vname3 = v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3
vname1, vname2, vname3 := v1, v2, v3
// 这种因式分解关键字的写法一般用于声明全局变量
var (
vname1 v_type1
vname2 v_type2
)
2. 函数声明
1. 函数声明
func function () int{}
2. 返回多个值的函数声明
func 函数名 (参数1,参数2,...) (返回值a 类型a, 返回值b 类型b,...)
//method A
func functions () (a int, b string) {
a = 100
b = "aa"
return
}
func 函数名 (参数1,参数2,...) (返回值类型1, 返回值类型2,...)
//method B
func functions () (int,string) {
a:=100
b:="aa"
return a, b
}
3. 结构体函数声明(此处我理解为类里面的方法)
func (this *结构体名) 函数名(参数 string) (返回值类型1, 返回值类型2){}
func (this *yourstruct) funcname(input string) ([]yourstruct, error){}
func main(){
var aaa yourstruct
bbb, err :=aaa.funcname("input")
}
4. 函数可见性规则
使用大小来区分函数可见性
大写是public类型
小写是private类型
1. 私有函数
func prifunc int{}
2. 公有函数
func pubfunc int{}
4. 数据类型
1. 整数类型
- uint8
- uint16
- uint32
- uint64
- int8
- int16
- int32
- int64
2. 浮点类型
- float32
- float64
- complex64
- complex128
3. 其他数字类型
- byte 类似uint8
- rune 类似int32
- uint 类似uint32或64
- int 与uint一样大
- uintptr 无符号指针
4. 派生类型
- 指针类型(Pointer)
- 数组类型
- 结构化类型(struct)
- Channel 类型
- 函数类型
- 切片类型
- 接口类型(interface)
- Map 类型
- 布尔型 false和true
- 字符串类型 string
5. 运算符
1. &取地址运算符
a:=100
b=&a
//输出a的地址
2. 赋值运算符
= 赋值
:= 声明并赋值
var a int
a = 100
d:=100
a:=100//错误,因为a已被声明
a,b := 100,200//正确,因为存在一个未被声明的变量b
_ = 100 //赋值给下划线表示丢弃该值
6. 关键字
1. const关键字
声明静态变量
const value int
2. var 关键字
定义变量
var value int
3. type 关键字
声明一般类型、接口和结构体
type newtype int
type intfa interface{}
type structure struct{}
4. func 关键字
声明函数
func function () int{}
5. nil 关键字
go里面所有的空值对应如下
bool -> false
numbers -> 0 //包括int,uint,complex等在内的数值类型
string -> ""
pointers -> nil
slices -> nil
maps -> nil
channels -> nil
functions -> nil
interfaces -> nil
6. defer 关键字
只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法。当defer语句被执行时,跟在defer后面的函数就会被延迟执行。直到包含该defer语句的函数执行完毕时,defer后面的函数才会被执行,不论包含defer语句的函数是通过return正常结束,还是由于panic导致的异常结束。你可以在一个函数中执行多条defer语句,它们的执行顺序与声明顺序相反。
package ioutil
func ReadFile(filename string) ([]byte, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
return ReadAll(f)
}
7. chan关键字
通道类型
8. new关键字
内建函数 new 用来分配内存,它的第一个参数是一个类型,不是一个值,它的返回值是一个指向新分配类型零值的指针
func new(Type) *Type
7. slice切片(此处我将他理解成vector)
[这位博主有非常详细的分析]https://www.01hai.com/note/av133981
slice数据结构
type slice struct {
data uintptr //数据指针头
len int //已用长度
cap int //总长度,string类型就是默认长度32的slice
}
一旦数据超出slice长度就会发生复制,生成新的slice
a []int
a = a.append(a, 1)//所以往slice新增数据都是这样赋值的
//创建slice
Varityname []int
//增加元素
Varityname = append(Varityname, 1)
8. 分支
1. switch
switch var1 {
case val1:
...
case val2:
...
default:
...
}
2. if
if condition {
process
}else{
process
}
3. if else
if condition1 {
process
}else if condition2{
process
}else{
process
}
9. range
Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对的 key 值。
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
10. 并发
Go 语言支持并发,我们只需要通过 go 关键字来开启 goroutine 即可。
goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。
同一个程序中的所有 goroutine 共享同一个地址空间。
语法格式如下:
go 函数名( 参数列表 )
通道(channel)是用来传递数据的一个数据结构。
通道的声明
ch := make(chan int)
ch := make(chan int, 100)
通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。
ch <- v // 把 v 发送到通道 ch
v := <-ch // 从 ch 接收数据, 并把值赋给 v
11. 接口
[这里有比较详细的用例]https://www.runoob.com/go/go-interfaces.html
go里面的空接口可以指代任何类型(无论是变量还是函数)
声明空接口
var adb interface{}
adb = 1
adb ="adafsd"
12.类型转换
go里面的的强制类型转换语法为:
int(data)
如果是接口类型的强制转成其他类型的语法为:
var asd interface{}
asd.(string)
go里面的强制转换是将值复制过去,所以在数据量的时候有比较高的运行代价