Golang系列(一)之基础篇
来源:互联网 发布:嵌入式系统编程 下载 编辑:程序博客网 时间:2024/06/08 13:28
一、初识Go语言
(一)概述
一个在语言层面实现了并发机制的类C通用型编程语言。
(二)Go关键字(25个)
(三)Go语言命令
Usage:go command [arguments]
二、顺序编程
1.变量
1.1变量声明
//1、单变量声明,类型放在变量名之后,可以为任意类型var 变量名 类型var v1,v2,v3 string //多变量同类型声明//2、多变量声明var { v1 int v2 []int}
1.2变量初始化
//1、使用关键字var,声明变量类型并赋值var v1 int=10//2、使用关键字var,直接对变量赋值,go可以自动推导出变量类型var v2=10//3、直接使用“:=”对变量赋值,不使用var,两者同时使用会语法冲突,推荐使用v3:=10
1.3变量赋值
//1、声明后再变量赋值var v intv=10//2、多重赋值,经常使用在函数的多返回值中,err,v=func(arg)i,j=j,i //两者互换,并不需要引入中间变量
1.4匿名变量
//Go中所有声明后的变量都需要调用到,当出现函数多返回值,并且部分返回值不需要使用时,可以使用匿名变量丢弃该返回值func GetName()(firstName,lastName,nickName string){ return "May","Chan","Make"}_,_,nickName:=GetName() //使用匿名变量丢弃部分返回值
2.常量
Go语言中,常量是编译时期就已知且不可变的值,常量可以是数值类型(整型、浮点型、复数类型)、布尔类型、字符串类型。
2.1字面常量
//字面常量(literal)指程序中硬编码的常量3.14“foo”true
2.2常量定义
//1、可以限定常量类型,但非必需const Pi float64 = 3.14//2、无类型常量和字面常量一样const zero=0.0//3、多常量赋值const( size int64=1024 eof=-1)//4、常量的多重赋值,类似变量的多重赋值const u,v float32=0,3const a,b,c=3,4,"foo" //无类型常量的多重赋值//5、常量赋值是编译期行为,可以赋值为一个编译期运算的常量表达式const mask=1<<3
2.3预定义常量
//预定义常量:true、false、iota//iota:可修改常量,在每次const出现时被重置为0,在下一个const出现前,每出现一次iota,其代表的值自动增1。const( //iota重置为0 c0=iota //c0==0 c1=iota //c1==1 c2=iota //c2==2)//两个const赋值语句一样可以省略后一个const( //iota重置为0 c0=iota //c0==0 c1 //c1==1 c2 //c2==2)
2.4枚举
枚举指一系列相关常量。
const( Sunday=iota //Sunday==0,以此类推 Monday Tuesday Wednesday Thursday Friday Saturday //大写字母开头表示包外可见 numberOfDays //小写字母开头表示包内私有)
3.类型
3.1基础类型
3.1.1布尔类型
//布尔类型的关键字为bool,值为true或false,不可写为0或1var v1 boolv1=true//接受表达式判断赋值,不支持自动或强制类型转换v2:=(1==2)
3.1.2整型
//1、类型表示//int和int32为不同类型,不会自动类型转换需要强制类型转换//强制类型转换需注意精度损失(浮点数→整数),值溢出(大范围→小范围)var v2 int32v1:=64v2=int32(v1)//2、数值运算,支持“+,-,*,/和%”5%3 //求余//3、比较运算,“<,>,==,>=,<=,!=”//不同类型不能进行比较例如int和int8,但可以与字面常量(literal)进行比较var i int32var j int64i,j=1,2if i==j //编译错误,不同类型不能进行比较if i==1 || j==2 //编译通过,可以与字面常量(literal)进行比较//4、位运算//Go(^x)取反与C语言(~x)不同,其他类似,具体见下表
3.1.3浮点型
//1、浮点型分为float32(类似C中的float),float64(类似C中的double)var f1 float32f1=12 //不加小数点,被推导为整型f2:=12.0 //加小数点,被推导为float64f1=float32(f2) //需要执行强制转换//2、浮点数的比较//浮点数不是精确的表达方式,不能直接使用“==”来判断是否相等,可以借用math的包math.Fdim
3.1.4复数类型
//1、复数的表示var v1 complex64v1=3.2+12i//v1 v2 v3 表示为同一个数v2:=3.2+12iv3:=complex(3.2,12)//2、实部与虚部//z=complex(x,y),通过内置函数实部x=real(z),虚部y=imag(z)
3.1.5字符串
//声明与赋值var str stringstr="hello world"
3.1.6字符类型
//1、byte,即uint8的别名//2、rune,即Unicode
3.1.7错误类型(error)
3.2复合类型
3.2.1数组(array)
数组表示同一类型数据,数组长度定义后就不可更改,长度是数组内的一个内置常量,可通过len()来获取。
//1、创建数组var array1 [5]int //声明:var 变量名 类型var array2 [5]int=[5]int{1,2,3,4,5} //初始化array3:=[5]int{1,2,3,4,5} //直接用“:=”赋值[3][5]int //二维数组[3]*float //指针数组//2、元素访问for i,v:=range array{ //第一个返回值为数组下标,第二个为元素的值}//3、值类型//数组在Go中作为一个值类型,值类型在赋值和函数参数传递时,只复制副本,因此在函数体中并不能改变数组的内容,需用指针来改变数组的值。
3.2.2切片(slice)
数组在定义了长度后无法改变,且作为值类型在传递时产生副本,并不能改变数组元素的值。因此切片的功能弥补了这个不足,切片类似指向数组的一个指针。可以抽象为三个变量:指向数组的指针;切片中元素的个数(len函数);已分配的存储空间(cap函数)。
//1、创建切片//a)基于数组创建var myArray [5]int=[5]{1,2,3,4,5}var mySlice []int=myArray[first:last]slice1=myArray[:] //基于数组所有元素创建slice2=myArray[:3] //基于前三个元素创建slice3=myArray[3:] //基于第3个元素开始后的所有元素创建//b)直接创建slice1:=make([]int,5) //元素初始值为0,初始个数为5slice2:=make([]int,5,10) //元素初始值为0,初始个数为5,预留个数为10slice3:=[]int{1,2,3,4,5} //初始化赋值//c)基于切片创建oldSlice:=[]int{1,2,3,4,5}newSlice:=oldSlice[:3] //基于切片创建,不能超过原切片的存储空间(cap函数的值)//2、元素遍历for i,v:=range slice{ //与数组的方式一致,使用range来遍历 //第一个返回值(i)为索引,第二个为元素的值(v)}//3、动态增减元素//切片分存储空间(cap)和元素个数(len),当存储空间小于实际的元素个数,会重新分配一块原空间2倍的内存块,并将原数据复制到该内存块中,合理的分配存储空间可以以空间换时间,降低系统开销。//添加元素newSlice:=append(oldSlice,1,2,3) //直接将元素加进去,若存储空间不够会按上述方式扩容。newSlice1:=append(oldSlice1,oldSlice2...) //将oldSlice2的元素打散后加到oldSlice1中,三个点不可省略。//4、内容复制//copy()函数可以复制切片,如果切片大小不一样,按较小的切片元素个数进行复制slice1:=[]int{1,2,3,4,5}slice2:=[]int{6,7,8}copy(slice2,slice1) //只会复制slice1的前三个元素到slice2中copy(slice1,slice1) //只会复制slice2的三个元素到slice1中的前三个位置
3.2.3键值对(map)
map是一堆键值对的未排序集合。
//1、先声明后创建再赋值var map1 map[键类型] 值类型//创建map1=make(map[键类型] 值类型)map1=make(map[键类型] 值类型 存储空间)//赋值map1[key]=value// 直接创建m2 := make(map[string]string)// 然后赋值m2["a"] = "aa"m2["b"] = "bb"// 初始化 + 赋值一体化m3 := map[string]string{ "a": "aa", "b": "bb",}//2、元素删除//delete()函数删除对应key的键值对,如果key不存在,不会报错;如果value为nil,则会抛出异常(panic)。delete(map1,key) //3、元素查找value,ok:=myMap[key]if ok{//如果找到 //处理找到的value值}//遍历for key,value:=range myMap{ //处理key或value}
3.2.4指针(pointer)
具体参考Go语言指针详解
3.2.5结构体(struct)
具体参考Go面向对象编程之结构体
3.2.6接口(interface)
具体参考Go面向对象编程之接口
3.2.7通道(chan)
具体参考Go并发编程之channel
4.流程语句
4.1条件语句
//在if之后条件语句之前可以添加变量初始化语句,用;号隔离if <条件语句> { //条件语句不需要用括号括起来,花括号必须存在 //语句体}else{ //语句体}//在有返回值的函数中,不允许将最后的return语句放在if...else...的结构中,否则会编译失败//例如以下为错误范例func example(x int) int{ if x==0{ return 5 }else{ return x //最后的return语句放在if-else结构中,所以编译失败 }}
4.2选择语句
//1、根据条件不同,对应不同的执行体switch i{ case 0: fmt.Printf("0") case 1: //满足条件就会退出,只有添加fallthrough才会继续执行下一个case语句 fmt.Prinntf("1") case 2,3,4: //单个case可以出现多个选项 fmt.Printf("2,3,4") default: //当都不满足以上条件时,执行default语句 fmt.Printf("Default")}//2、该模式等价于多个if-else的功能switch { case <条件表达式1>: 语句体1 case <条件表达式2>: 语句体2}
4.3循环语句
//1、Go只支持for关键字,不支持while,do-while结构for i,j:=0,1;i<10;i++{ //支持多个赋值 //语句体}//2、无限循环sum:=1for{ //不接条件表达式表示无限循环 sum++ if sum > 100{ break //满足条件跳出循环 }}//3、支持continue和break,break可以指定中断哪个循环,break JLoop(标签)for j:=0;j<5;j++{ for i:=0;i<10;i++{ if i>5{ break JLoop //终止JLoop标签处的外层循环 } fmt.Println(i)}JLoop: //标签处...
4.4跳转语句
//关键字goto支持跳转func myfunc(){ i:=0 HERE: //定义标签处 fmt.Println(i) i++ if i<10{ goto HERE //跳转到标签处 }}
5.函数
5.1函数定义与调用
//1、函数组成:关键字func ,函数名,参数列表,返回值,函数体,返回语句//先名称后类型func 函数名(参数列表)(返回值列表){ //参数列表和返回值列表以变量声明的形式,如果单返回值可以直接加类型 函数体 return //返回语句}//例子func Add(a,b int)(ret int,err error){ //函数体 return //return语句}//2、函数调用//先导入函数所在的包,直接调用函数import "mymath"sum,err:=mymath.Add(1,2) //多返回值和错误处理机制//可见性,包括函数、类型、变量//本包内可见(private):小写字母开头//包外可见(public):大写字母开头
5.2不定参数
//1、不定参数的类型func myfunc(args ...int){ //...type不定参数的类型,必须是最后一个参数,本质是切片 for _,arg:=range args{ fmt.Println(arg) }}//函数调用,传参可以选择多个,个数不定myfunc(1,2,3)myfunc(1,2,3,4,5)//2、不定参数的传递,假如有个变参函数myfunc2(args ...int)func myfunc1(args ...int){ //按原样传递 myfunc2(args...) //传递切片 myfunc2(args[1:]...)}//3、任意类型的不定参数,使用interface{}作为指定类型func Printf(format string,args ...interface{}){ //此为标准库中fmt.Printf()函数的原型 //函数体}
5.3多返回值
//多返回值func (file *File) Read(b []byte) (n int,err error)//使用下划线"_"来丢弃返回值n,_:=f.Read(buf)
5.4匿名函数与闭包
//1、匿名函数:不带函数名的函数,可以像变量一样被传递func(a,b int,z float32) bool{ //没有函数名 return a*b<int(z)}f:=func(x,y int) int{ return x+y}//2、闭包
6.错误处理
1、error接口
//定义error接口type error interface{ Error() string}//调用error接口func Foo(param int) (n int,err error){ //...}n,err:=Foo(0)if err!=nil{ //错误处理}else{ //使用返回值}
2、defer[延迟函数]
语法:defer function_name()
1)defer在声明时不会执行,而是推迟执行,在return执行前,倒序执行defer[先进后出],一般用于释放资源,清理数据,记录日志,异常处理等。
2)defer有一个特性:即使函数抛出异常,defer仍会被执行,这样不会出现程序错误导致资源不被释放,或者因为第三方包的异常导致程序崩溃。
3)一般用于打开文件后释放资源的操作,比如打开一个文件,最后总是要关闭的。而在打开和关闭之间,会有诸多的处理,可能会有诸多的if-else、根据不同的情况需要提前返回
f, = os.open(filename)defer f.close()do_something()if (condition_a) {return}do_something_again() if (condition_b) {return}do_further_things()
4)defer示例
package mainimport "fmt"func deferTest(number int) int { defer func() { number++ fmt.Println("three:", number) }() defer func() { number++ fmt.Println("two:", number) }() defer func() { number++ fmt.Println("one:", number) }() return number}func main() { fmt.Println("函数返回值:", deferTest(0))}/*one: 1two: 2three: 3函数返回值: 0*/
阅读全文
0 0
- Golang系列(一)之基础篇
- Golang基础语法(一)
- 技术系列之 网络模型(一)基础篇
- 技术系列之 网络模型(一)基础篇
- 【原创】技术系列之 网络模型(一)基础篇
- Android基础系列之Service(一)
- Python系列(一)之Python基础
- 自定义View系列(一)基础篇
- RxJava系列(一、基础篇)
- Android 单排上王者系列之RxJava基础篇一
- Docker从零单排系列之基础篇(一)
- BUIW系列笔记之BUIW基础(一)
- c++ 工程基础之STL系列 (一) vector
- 基础算法系列(一)查找算法之顺序查找
- Java加密系列之(一)加密基础
- Dubbo系列(一)Dubbo之基础概念
- golang语言基础篇
- 教你学会java基础多线程系列文章之中级篇(一)
- HTML视频注意点
- oracle 12c database安装步骤
- df、du 命令和磁盘分区
- Linux系统parted分区GPT格式
- 第一个storm代码-wordcount-本地模式
- Golang系列(一)之基础篇
- 学习总结2017/11/2
- ShadowSocksR SSR 安装脚本 CentOS 6
- nginx源码阅读(六).内存池
- 【1701H1】【穆晨】【171102】连续第二十三天总结
- centos6.9 编译openJdk源码
- 7.2.2生成可重集的排列
- 136. Single Number
- 初学Spring框架day02 2017-11-02