Go
简介
C/C++ 快执行速度-----Golang----Python/Ruby
Go优势
- 编译型语言,运行速度快,但有动态语言的部分特性,开发效率高
- 语言层面支持并发
- 内置Runtime,GC
- 内嵌C支持,可直接引用C代码
1. hello world
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello World!")
}
package: 包名
import: 导包
main函数:go程序的入口,与python,c++,java不同,go程序的main函数是不含参的,在控制台中输入的参数在org.Args()中
方法:
func 函数名(参数列表)(返回值列表){
//函数体
}
注意:函数题的左花括号必须在函数名后,不能另起一行
注释:同C++相同
//注释
/* 注释 */
2. 变量
关键字 25个
变量声明:
var [变量名] [类型]
多变量
var [变量名1,变量名2] [类型]
var x int
var x,y int
var(
x int
y int
)
变量初始化,类似于python,可自动推导类型 ,':='操作符是声明并赋值操作
var x int =10
var x=10 //自动推导类型
x:=10 //自动推导类型
变量赋值
var x int
x=1
var x,y,z int
x,y,z=1,2,3
i:=1
j:=2
i,j=j,i//交换
常量修饰符 const
字面量:程序中硬编码的常量
const x=1
const(
x=1
y=2
)
iota枚举 在常量声明中使用
常量声明可以使用iota常量生成器初始化,生成一组以相似规则初始化的常量,不用每行都写一遍初始化表达式,第一行为0,其他行为上一行+1
const(
x=iota//0
y=iota//1
z=iota//2
)
//每遇到const,iota置0
const(
x,y,z=iota,iota,iota//同一行不变
)
const(
x=iota//0
y="helloworld"
z=iota//2
)
自定义类型
type Newtype int
const (
T1 Newtype = iota // 0
T2 // 1
T3 // 2
T4 // 3
)
//跳过一些值
type AudioOutput int
const (
OutMute AudioOutput = iota // 0
OutMono // 1
OutStereo // 2
_
_
OutSurround // 5
)
通过表达式定义数量级
type ByteSize float64
const (
_ = iota
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)
)
3.基础数据类型
- 整型
int uint
int8 uint8
int32 uint32
int64 uint64
uintptr 以存储指针的uint32或uint64整数
- 浮点型
go float32 float64
- 布尔型
bool
var v bool
v=1 //编译错误
v=bool(1) //编译通过
- 字节型(uint8的别名,代表utf-8字符串的单个字节的值)
byte
- 字符型(代表单个unicode字符)
rune
- 字符串
string
- 复数
complex64 complex128
var x=1.0+2i complex64
x=complex(1.0,2)
4. 格式化输出
fmt.Printf()输出格式字符串
格式 | 含义 |
---|---|
%% | 输出一个%字面量 |
%b | 二进制 |
%c | 字符型 |
%e | 科学计数法,使用e(浮点数、复数) |
%E | 科学计数法,使用E(浮点数、复数) |
%f | 浮点数、复数 |
%g | 以最为紧凑的方式输出(浮点数%e、%f、复数) |
%G | 以最为紧凑的方式输出(浮点数%E、%f、复数) |
%o | 八进制 |
%p | 十六进制,前缀为0x,字母使用小写的a-f表示 |
%q | 字符串或者字节切片[]byte,或者是以单引号括起来的数字 |
%t | 布尔类型 |
%T | 输出值得类型 |
%U | Unicode表示法表示的整型码点 |
%v | 使用默认格式输出的内置或者自定义类型的值 |
%x | 十六进制a-f |
%X | 十六进制A-F |
5. 类型转换
go语言类型转换只可以显式的进行
var x int
x=1
y:=float32(x)
6. 类型别名
type long int64
var x long=1000
7. 运算符
运算符 | |
---|---|
+ | |
- | |
* | |
/ | |
% | |
++ | 没有前自增 |
-- | 没有前自减 |
== | |
!= | |
|| | |
& | |
| | |
^ | |
<< | 左移 |
>> | 右移 |
= | |
+= | |
-= | |
*= | |
/= | |
%= | |
<<= | |
>>= | |
&= | |
|= | |
^= | |
& | 取地址 |
* | 指针取值 |
优先级
8. 流程控制
- if语句
if a==0 {//条件表达式不写括号
//code
}else{//左括号与else同行
//code
}
if a:=0;b==0{//初始化;条件表达式
//code
} else if b>1{
//code
}
- for语句
for i:=1;i<100;i++{
//code
}
s:="abc"
for i :=range s{//range 支持string/array/slice/map
fmt.Printf("%c\n",s[i])
}
for _,i :=range s{//index,value
fmt.Printf("%c\n",i)
}
-
switch语句
每个case语句默认带有break,需要执行多个case时,使用fallthrough强制执行后面语句
score:=100
switch score{
case 100:
//code
case 90:
//code
fallthrough
case 60,70,80:
//code
default:
//code
}
switch{//不写条件
case score>=90:
//code
default:
//code
}
switch score=60;{//初始化,但不写条件
case score>=90:
//code
default:
//code
}
-
break
跳出当前循环
-
continue
跳过本次循环
func my_fun{
LABEL:
for i:=0;i<100;i++{
for{
//code
break LABEL//跳出所有循环
continue LABEL//跳过for{}循环,外层for继续
}
}
}
-
goto
跳转到当前函数内定义标签
func my_fun{
LABEL:
for i:=0;i<100;i++{
for{
//code
goto LABEL//跳转至LABEL
}
}
}
9. 函数
func FuncName(/*参数列表*/) (o1 type1, o2 type2/*返回类型*/) {
//code
return v1, v2 //返回多个值
}
不定参数
func my_func(args ...int){//无返回值
for _,arg:=range args{
//code
}
}
有返回值
func my_func() int{//返回值不命名
for _,arg:=range args{
//code
}
}
func my_func()(value int){//返回值不命名
for _,arg:=range args{
//code
}
}
func my_func() (int,int){//多返回值不命名
for _,arg:=range args{
//code
}
}
func my_func()(value int,value2 ){//返回值不命名
for _,arg:=range args{
//code
}
}
9.1 函数类型
Go中函数也是一种类型,可以作为函数的参数,有相同入参和出参的函数属于同一类型
type FuncType func()//声明函数类型,无参无返回值
type FuncType func1(int,int) int//声明函数类型,有参有返回值
func cal(a,b int,f FuncType)(res int){
res=f(a,b)
return
}
func add(a,b int) int {
return a+b
}
func main(){
res:=cal(1,1,add)
}
9.2 匿名函数
不要函数名的一种实现函数的方法
闭包:捕获同一作用域的变量,不管在何处调用闭包,都可以使用该变量,闭包存在,变量不会失效,闭包中的变量是引用,在闭包中改变变量会改变原来的值。
f:=func(){//无参匿名函数
//code
}
f()
type FuncType func()
var f1 FuncType=f
f1()
f:=(){
//code
}()//此处的()会使该匿名函数直接调用
f2:=func(a,b int) (res int){
res=a+b
return
}(1,1)//直接传参调用
10. 包权限
public: 包中成员首字母大写,包外可访问
private:包中成员首字母小写,仅包内访问
main包:
函数入口,且一个程序只有一个main,main()是程序的入口
main()和init()函数:
没有入参和出参。程序执行时会先执行init()再执行main(),且包中可包含任意个init()
如果一个包被多个包引用,则程序中只会导入一次
别名导包:
import (
io "fmt"
)
空白导包:空白标识符:_
import (
_ "fmt"
)
11. 指针
默认值:nil
. : 访问目标成员,不支持指针运算
&取地址,*取值
new(T):创建一个T类型的匿名变量,为T类型的新值分配并清零一块内存,返回*T
12. 数组
var a [10]int//[]内为长度,必须是常量,后面是数组类型
//遍历
for i := 0; i < 10; i++ {
a[i] = i + 1
fmt.Printf("a[%d] = %d\n", i, a[i])
}
for i, v := range a {
fmt.Println("a[", i, "]=", v)
}
相关函数:
len、cap:求长度
初始化:
a:=[3]int{1,2,3}
a:=[...]int{1,2,3}
a:=[5]int{2:10,3:10}
//二维
a:=[2][2]int{{1,2},{3,4}}
b:=[3]int{1,2}
var d [3]int
d=a
动态数组、切片:声明时方括号不添加长度
切片声明:
arr:=[]int{1,2,3}
var arr []int
arr=make([]int,2)//make 开辟空间
arr=make([]int,2,5)//make 开辟空间,第一个参数为切片长度,第二个参数为切片容量
var arr []int=make([]int,3)
arr:=make([]int,3)//自动推导类型
切片的追加
append(arr,3)
切片扩容
向一个容量cap满的切片追加元素时,容量将增加2倍
13 Map
声明
var myMap=map[string]string
var myMap=map[string]string
myMap=make(map[string]string,10)
myMap:=make(map[string]string)
myMap:=map[string]string{
'1':'1'
}
使用
//添加
myMap["1"]="1"
//遍历
for k,v := range myMap{
//...
}
//删除
delete(myMap,"1")
14 结构体
type Book struct{
title string
}
15 类的定义
//类名大写,其他包也可以访问
type Book struct{
//属性名大写,公有属性
Title string
}
//传参是一个类的拷贝,不会影响原来的对象
func (this Book) GetTitle(){
return this.title
}
func (this Book) SetTitle(name string){
this.title=name
}
//类的方法
//地址传参
func (this *Book) GetTitle(){
return this.title
}
func (this *Book) SetTitle(name string){
this.title=name
}
类的继承
type Math struct{
Book//继承该类
page int//新的属性
}
//重写方法
func (this *Math)GetTitle(){
//...
}
//定义子类
math1:=Math{Book{"math1"},100}
var math1 Math
math1.Title="math1"
多态
//定义接口
type Book interface{
getName()
}
//第一个子类
type Math struct{
name string
}
func (this *Math)GetName(){
//...
}
//第二个子类
type English struct{
name string
}
func (this *English)GetName(){
//...
}
var Book book
book=&Math("math1")
book.GetName()
interface空接口万能类型
//可以传入任何参数
func test(arg interface{}){
fmt.Println("...")
}
16 断言机制
//判断arg是否为string类型
//第一个返回值为如果断言成立,具体的参数值
//第二个为断言是否成立
value,ok:=arg.(string)
变量的结构
变量的内置pair
func main(){
tty,err:=os.OpenFile("/dev/tty",os.O_RDWR,0)
var r io.Reader
//r:pair<type:*os.File,value:"/dev/tty">
r=tty
var w io.Writer
//w:pair<type:*os.File,value:"/dev/tty">
w=r.(io.Reader)
//此处仍然可以断言成功,内置pair没有变化
w.Write([]byte("Hello!"))//往终端写
}
17 反射(reflect包)
//返回一个变量的值,为空时返回0
func ValueOf(i interface{})Value{
//...
}
//返回一个变量的类型,为空时返回nil
func TypeOf(i interface{})Value{
//...
}
结构体标签
//keyvalue结构
type Book struct{
page int `info:"page",doc:"math"`
name string `info:"math"'`
}
//利用反射解析结构体标签
b:=&Book()
t=reflect.TypeOf(b).Elem()
for i:=0;i<t.NumField();i++{
taginfo:=t.Field(i).Tag.get("info")
taginfo:=t.Field(i).Tag.get("doc")
}
18 结构体标签转Json
package main
import (
"encoding/json"
"fmt"
)
type Book struct {
Title string `json:"title"`
Page int `json:"page"`
}
func main() {
//对象转json
math := Book{"math", 100}
jsonStr, err := json.Marshal(math)
if err != nil {
fmt.Println("json marshal error")
return
}
fmt.Printf("%s\n", jsonStr)
//jsonStr:={"title":"math","page":100}
//jsonz
book1:=Book{}
err=json.Unmarshal(jsonStr,&book1)
if err!=nil{
fmt.Println("json unmarshal error")
return
}
fmt.Printf("%v", book1)
}
19 goroutine
创建协程
go func(){
//...
func(){
//...
}()
}()
go func(a int,b int)bool{
return true
}(10,10)
goroutine之间通信
channel(管道)
//定义一个channel
c:=make(chan int)
go func(){
//将一个整型发送至channel
c<-100
}()
//从管道中读取数据
num:=<-c
无缓冲channel
管道中只能存在一个数据
只有读端或者只有写端,将会导致阻塞
ch:=make(chan int)
//管道容量为1
//len(ch)=0,cap(ch)=1
有缓冲channel
管道中可存储多个数据
当管道为空,从管道读取会导致阻塞,管道满,往管道写数据也会导致阻塞
ch:=make(chan int,10)
//管道容量为10
//len(ch)=0,cap(ch)=10
关闭channel
当确定没有数据发送了,显式地关闭channel,关闭channel后仍然可以接收数据,直到管道中没有数据
close(chan)
//data为channel中的数据,ok为true表示channel没有关闭,或管道中还有数据,false表示channel已经关闭且没有数据
//关闭后再向channel发送数据会报错
data,ok:=<-chan
//这里的if语句会先执行前面一条语句,并将ok作为条件表达式
if data,ok:=<-chan;ok{
//...
}
channel与range
//使用range从channel(channel没有关闭时)中读取数据
for data:=range chan{
//...
}
//等同于
for{
if data,ok:=<-chan;ok{
//...
}else{
break
}
}
channel与select
select:单流程下一个go只能监控一个channel的状态,select可以同时监控多个channel的状态
select{
case <-chan1:
//...
case <-chan2:
//...
default:
//...
}
20 Go Modules
GOPATH:
- 无版本控制
- 无法同步一致第三方版本号
- 无法指定当前项目引用的第三方版本号