Go基本使用
一、第一个go语言程序
1、新建一个go项目:File--New--Progect
2、新建一个Go文件:File--New--Go File
3、在编辑区内写入下列代码:
package main import "fmt" func main() { fmt.Println("hello world!") }
4、右击编辑区,选择run运行代码,控制台中会得到如下结果:
代码解释:
1、package main :
用来表示当前文件是一个可执行文件,表明本文件属于根目录
2、import “fmt” :
import是用来导入别人已经写好的代码(代码包),“fmt”是包的名字,这样我们就可以使用别人写好的代码了,“fmt”是Go自带标准库中的一个包。
3、func main(){ 函数体代码.. } :
这串代码表示的是一个函数,{}内的代码叫做函数体代码。一般的函数长这样:func 函数的名字(){ 函数体代码.. },这里的func main(){ 函数体代码.. }是一个特殊的函数,固定写法,叫做程序主函数,是一个程序的入口,当你运行程序的时候,执行的就是这个程序主函数的函数体代码。
4、fmt.Println("hello world!"):
刚刚我们提到过,“fmt”是人家写好的代码,“雇佣”不是目的,目的是要使用它的功能。我们通过.功能的名字(...)来调用它的功能,这里fmt.Println("hello world!")就是在调用fmt众多功能中的Println()功能,在屏幕中输出你指定的内容。
二、四个常用命令
1、go run:会先编译后执行,但不会保存编译结果
go run 文件名
go run 项目名
2、go build:会编辑制定程序,结果会放到cmd当前目录下
go build 文件名
go build 项目名
go build -o 新路径/名字 项目名(文件名)
3、go install
go install 有main的项目 会编辑制定程序,结果会放到src/bin目录下
go install 没有main的项目 会编辑制定程序,结果会放到src/pkg目录下
4. go fmt
go fmt 文件名
go fmt 项目名
三、变量
1、变量的定义:go语言中,变量的定义有5种方式:
①var 变量名1,变量名2,,,类型
var a int
var b,c string
var d bool
这种形式下,你虽然没有指定变量的值,但Go语言会给它一个初始值:
fmt.Println(a) # 0 fmt.Printf("%q,%q",b,c) # "" "" 如果直接用Println是看不到""(空串)的 fmt.Printf(d) # false
int类型的初始值:0,string类型的初始值:“”,bool类型的初始值:false。
②var 变量名1,变量名2,,,类型 = 变量值1,变量值2,,,
var a int = 123 var b,c string = "老王","小丽"
声明变量,并且给定初始值
fmt.Println(a) # 123 fmt.Println(b,c) # "老王","小丽"
③var 变量名1,变量名2,,, = 变量值1,变量值2,,,
var a = 123 var b,c = "老王",true
这种方式省略了数据类型,那这么写变量的数据类型又是什么呢?在你不指定数据类型的时候,Go语言会根据你传的变量值,自动判断类型
fmt.Println(a) # 123 fmt.Println(reflect.Typeof(a)) # int fmt.Println(b) # "老王" fmt.Println(reflect.Typeof(b)) # string fmt.Println(c) # true fmt.Println(reflect.Typeof(c)) # bool
④变量名1,变量名2,,,:= 变量值1,变量值2,,,
a := 123 b,c := "老王",true
这种形式省略了var,用“:=”取代了“=”
fmt.Println(a) # 123 fmt.Println(reflect.Typeof(a)) # int fmt.Println(b) # "老王" fmt.Println(reflect.Typeof(b)) # string fmt.Println(c) # true fmt.Println(reflect.Typeof(c)) # bool
虽然这种方式是形式③的一种简便写法,但是它的使用范围受到了限制,这一点尤其重要,需要特别注意:
func main(){ a,b := 123,true fmt.Println(a,b) # 123 true }
这种形式的定义变量只能写在函数内部,不可写在函数外部,如果写在外部会直接报错:
a,b := 123,true func main(){ fmt.Println(a,b) } # 这么写程序会报错:syntax error: non-declaration statement outside function body,意思是:没有用var关键词声明的变量超出了函数体之外
⑤var (
变量名1 = 变量值1
变量名1,变量名2,,, = 变量值1,变量值2,,,
...
)
var( a int= 123 b,c = "老王",true )
强调:用“:=”这种形式定义变量只能写在函数体内,用“var”定义变量既可以写在函数体内也可以写在函数体外
2、变量的赋值
变量的赋值操作很简单,直接使用“=”即可,变量名1,变量名2,,, = 新值1,新值2,,,
var a,b,c = 11,22,33 # 这里我定义变量之后,a、b、c的类型就已经固定为int类型 a,b = 44,55 # 这里给a,b重新赋新值(值的类型还是int),44,55 c = "老王" # 这行报错,c的原本类型为int,但我这里给了它string类型的值,就会报错
强调:变量赋值的唯一注意点就是前后类型要一致
3、变量名的命名规范
①、变量只能是字母、数字、下划线的任意组合
②、变量名不能以数字开头
③、不能使用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
④、驼峰体:首字母小写,后面每个独立单词的首字母大写,如:sonOfBitch、ageOfStudents
下划线体,如:son_of_bitch、age_of_students
四、常量
1、常量的定义
定义变量用的是var关键字,定义常量我们用const关键字。定义常量的方法有3种:
①const 常量名1,常量名2,,,, 数据类型 = 常量值1,常量值2,,,
const a int = 4 const b,c string = "张三","李四"
②const 常量名1,常量名2,,, = 常量值1,常量值2,,, 常量也是可以不指定数据类型,让程序通过值来自动判断类型的
const a = 4 const b,c = "张三",“李四” fmt.Println(reflect.Typeof(a)) # int fmt.Println(reflect.Typeof(b)) # string
③const (
常量名1 = 常量值1
常量名1,常量名2,,, = 常量值1,常量值2,,,
...
)
const( a int= 123 b,c = "老王",true )
注意:在常量组中
空常量的数据类型与值要与上方最近的非空常量的数据类型与值相同
空常量的个数,要与上方最近的非空常量个数一致
const( a int= 123 b c,d = "老王",true e,f ) fmt.Printli(reflect.Typeof(b),b) # int 123 fmt.Printli(reflect.Typeof(e),e) # string "老王" fmt.Printli(reflect.Typeof(f),f) # bool true
注意:常量可以出现定义了但却不使用的情况,这一点和变量相反。常量一旦定义,就不能被修改。
2.自增常量组——常量组的特殊用法
引子:
有一个需求:我需要定义4个常量,分别是a,b,c,d,他们的值分别是1,2,3,4。如何定义?是不是很简单?
const( a = 1 b = 2 c = 3 d = 4 )
这么定义烦不烦?如果我要定义10个呢,是不是你还要写10个“=”?为了解决这个问题,就有了自增常量组的概念。
什么是自增常量组:
常量组就是const()定义的一组常量,自增就是有规律的自动增加,不需要手动一个个赋值。
什么样的场景适合用自增常量组:
比如说,“monday,tuesday,wednesday,thursday,friday,saturday,sunday”,从星期一到星期天,我们分别可以用1,2,3,4,5,6,7这样用规律性增加的数字去表示,并且他们是一个固定的值,不会随着程序的运行而变化。
如何使用自增常量组:
①常量计数器iota
iota是一个常量计数器,顾名思义,计数器得到的是一个值,表示的是你当前常量个数,iota的初始值为0,类型默认为int,也可自行指定为其它数字类型。如下列代码:
const( a = iota # 用赋值的形式调用iota,初始值为0,类型为int b # b的值会被自动赋值为1,类型为int c # c的值会被自动赋值为2,类型为int d # d的值会被自动赋值为3,类型为int )
②占位符_
还是刚刚那个场景,如果我要给a,b,c,d分别赋值1,2,3,4,呢,可iota又是从0开始的怎么办? 这里就引出了一个新的概念,占位符“_”,就是占着茅坑不拉shit的意思,只是占了个位置,不会被存储,也不可被调用。用法看代码:
const( _ = iota # _占位,调用iota,初始值为0,类型为int a # a = 1 b # b = 2 c # c = 3 d # d = 4 )
③iota的中断和恢复
const( _ = iota #_占位,调用iota,初始值为0,类型为int a # a = 1 b # b = 2 c string = "老王" # 这里iota自动赋值被中断,但计数没有停止 d # d和c的类型和值相同,string,"老王" e = iota # iota自动赋值恢复,取计数值,5 f # f = 6 )
④多个iota同时使用
可以在常量组的多常量定义中,使用多个iota,各自单独计数,前提是每行常量列数相同
const( a,b = iota,iota # a = 0 b = 0 类型int b,c # b = 1 c = 1 d,e # d = 2 e = 2 )
⑤iota参与运算
iota可以直接参与运算:
const( a = iota * 2 # 0 b # 2 c # 4 d # 6 )
⑥自定义iota的类型
iota的默认类型是int,也可以使用其它数字类型,也可以使用基础类型为数字类型的自定义类型 使用其它数字类型的代码:
const( a float32 = iota # 指定为小数类型 b )
使用基础类型为数字类型的自定义类型:
type id int8 const( a id = iota # 指定为id类型 b )
五、基本运算符
以下假设A=10,B=20:
注意:
①变量一旦定义,类型就确定了
②2这样的整形数字会被自动转换成浮点型数字
③2.0这样的浮点型数字会被自动转换成整形数字
④同类型之间才能进行运算
2、关系运算符
以下假设A=10,B=20:
3、逻辑运算符
以下假设A=true,B=false:
4.位运算符
十进制转二进制:
所以10进制中10的2进制就是01010
二进制转十进制:
以下假设A = 60 , B = 13 ,A的8位二进制:00111100 ,B的8位二进制:00001101
# 按位与运算符&: A: 0 0 1 1 1 1 0 0 B: 0 0 0 0 1 1 0 1 A&B: 0 0 0 0 1 1 0 0 对应位比较,如果都为1,那么按位与的结果为1,否则为0 # 按位或运算符|: A: 0 0 1 1 1 1 0 0 B: 0 0 0 0 1 1 0 1 A|B: 0 0 1 1 1 1 0 1 对应位比较,只要有一个为1,那么按位或的结果为1,否则为0 # 按位异或运算符^: A: 0 0 1 1 1 1 0 0 B: 0 0 0 0 1 1 0 1 A^B: 0 0 1 1 0 0 0 1 对应位比较,只要不相同就为1,否则为0 # 左移运算符<< A: 0 0 1 1 1 1 0 0 A<<2: 1 1 1 1 0 0 0 0 A<<3: 1 1 1 0 0 0 0 0 各二进位全部左移n位,超出总位数就丢弃 在不丢弃的情况下,相当于10进制上乘以了2的n次方 # 右移运算符>> A: 0 0 1 1 1 1 0 0 A>>2: 0 0 0 0 1 1 1 1 A>>3: 0 0 0 0 0 1 1 1 各二进位全部右移n位,超出范围就丢弃 在不丢弃的情况下,相当于10进制上除以了2的n次方
5、赋值运算符
6.其它运算符