1.第一个Go程序
package main import "fmt" func main() { fmt.Println("hello,world") fmt.Println("你好") }
第一行:每个Go源代码文件的开头都是一个package声明,表示该Go代码所属的包。Go语言中是通过包来对代码进行管理的。那么什么是包呢?我通过一个例子来解释一下包的概念。例如:有一家公司叫"京东",该公司有一个项目叫"京东网上商城",该项目下面有管理"客户信息"的代码,另外一家公司叫"淘宝",该公司也有一个项目叫"淘宝网上商城",该项目下面也有管理"客户信息"的代码,我开发的"客户管理软件",既要用到"京东"的客户信息管理代码,也要用到"淘宝"的客户信息管理代码,为了能够很好的区分,我们在使用时必须写清楚,客户的信息管理代码到底是来自哪个商城,所以我可以这样写 import "京东",表示所使用的"客户信息代码"是来自"京东"的,那么"京东"就是一个标识,也就是包。所以说,包就是一个标识,标志着着你写的Go代码来自哪,这样代码管理非常清晰,使用也非常方便。
不管你创建多少个包,要想让程序运行,必须包含一个main包。如果缺少该包,程序是无法运行的。
第三行代码:import表示导入,"fmt"是包名。不管是使用我们自己定义的包还是Go自带都是通过import导入的,"fmt"是Go自带的包,该包包含了怎样将信息打印在电脑屏幕上。注意包名要用""表示。
第五行代码:表示程序的入口,程序就是从该位置开始执行的,就像是教室的门口一样,注意该行代码是固定的写法,func 与main之间必须有空格,同时main后面必须带小括号,后面的一对大括号表示要完成的具体工作,也就是完成具体任务的代码必须写在一对大括号内。func表示后面跟着的main是一个函数,函数必须有一对小括号。什么是函数呢?现在大家可以先理解与我们在数学中学到的函数是一样的,都是实现某个具体的功能,例如我们学习的三角函数等。Main函数实现的就是入口功能。再次强调一下,Go语言中的函数前面必须加上func这个单词,而且函数名称后面必须跟一对小括号。
第六行代码:就是使用了fmt包(注意具体使用的时候不需要加上双引号)中的Println函数,将要"hello,world" 打印在屏幕上。这行代码要注意的是,fmt包与Println函数之间是用.(点连接的),该点是在半角输入法状态下输入,同时Println函数第一个字母P是大写的,不能写成小写,也就是说Go语言是区分大小写的,有很多同学在这里容易出错。将要输出的信息写在Println函数的括号内(注意括号也是在半角状态下输入的),并且用双引号包裹起来(双引号也是半角状态下输入的)。
2.变量
2.1 什么是变量
所谓的变量简单的理解就是计算机用来存储数据的。我们可以理解变量就像我们去超市买商品时用到的购物车,我们先将商品从货架上拿下来,放到购物车中,结账时在从购物车中取出商品。计算机通过变量来保存数据实际上将数据存储到计算机的内存中,这里我们可以画一个图给大家理解一下。
计算机将内存划分成不同的区域,数据就是存储在这些区域中,那么怎样从这些区域中将数据取出来呢?计算机将每块区域都加上了一串数字,作为编号。通过该编号就可以将数据取出来了,但是问题是,这一串数字对我们程序员来说是非常难记忆的,
为了解决这个问题,我们可以通过变量的方式来表示存储的数据,如下图:
我们给每个存储区域加上了Number1,Number2,Name等符号,这样通过这些符号来存储数据,然后通过这些符号取出数据就非常容易,方便了。这些符号就是变量。
2.2 变量类型
我们现在理解了变量可以用来存储数据,但是我们要存储的数据类型是各种各样的,例如:整数,小数,文本等等。所以我们必须在定义变量时就要告诉计算机,定义的变量存储是什么类型的数据。那么在内存中就可以根据不同的类型来开辟不同的存储空间。
生活中关于“类型“的例子:
2.3 变量的定义和使用
所谓声明变量就是创建一个变量,并且指定该变量存储什么类型的数据。
Go语言引入了关键字var,而类型信息放在变量名之后。
定义变量的格式是:var 变量名 数据类型 = 值。
在定义变量时也可以先声明变量,然后再赋值,格式是:var 变量名 数据类型,此时只是声明了此变量;变量名 = 值,此时是为变量赋值(当只声明变量时,整型的变量的初始值是0;字符串类型的变量初始值是空字符串)。
示例如下:
package main import "fmt" func main() { //变量的定义和使用 //变量定义格式 //var 变量名 数据类型(声明) //var 变量名 数据类型 = 值 (定义) //int 表示的是整型 可以存储整数
//定义 var a int = 100 fmt.Println(a)
//修改变量的值 a = 123 fmt.Println(a) //声明 var b int
//赋值 b = 10
//使用 fmt.Println(b) }
结果如下:
64
128
10
2.4 自动推导类型
在给变量赋值时,我们感觉非常麻烦,有没有更简单的给变量赋值的方式,我们可以使用自动推导类型,自动推导类型就是根据值的类型决定变量的数据类型。
格式是:变量名 := 值
具体示例如下:
package main import "fmt" func main() { //var a int = 10 //自动推导类型(根据值来确定变量的类型) //变量名:=值 a := 10 //int b := 3.14 //float64 fmt.Println(a)
//通过自动推导类型定义的浮点型数据,数据类型都是float64 fmt.Println(b) //通过格式化打印数据类型 //%T 是一个占位符 表示输出一个数据对应的类型 fmt.Printf("%T", a) fmt.Println() fmt.Printf("%T", b) }
结果如下:
10
3.14
int
float64
func main() {
//var a string = "你好"
//通过自动推导类型创建字符串
a := "你好" //创建变量
a = "我不好" //赋值
fmt.Println(a)
fmt.Printf("%T", a)
}
结果如下:
我不好
string
所谓自动推导类型,就是不用通过var 声明变量,不用指定类型,直接在变量名后面跟":"号,同时完成赋值。那么Go会根据所赋的值自动推导出变量的类型。如果给变量赋值为小数,那么该变量的类型为小数类型(浮点)。
2.5 多重赋值和匿名变量
我们给变量赋值,可以采用自动推导的方式,如果想一次使用自动推导的方式,给多个变量赋值,应该怎样实现呢?
var格式定义:var 变量名1 变量名2 ..... = 值1 值2 .......
自动推导类型:变量名1 变量名2 ..... := 值1 值2 .......
具体如下:
package main
import "fmt"
func main() {
//多重赋值
//定义多个变量
//var a, b, c int = 10, 20, 30
//自动推导类型创建多个变量
//a, b, c := 10, 20, 30
//自动推导类型创建多个不同类型的变量
a, b, c := 10, 3.14, "hello"
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
//
转义字符 表示换行
fmt.Printf("%T
", a)
fmt.Printf("%T
", b)
fmt.Printf("%T
", c)
}
结果如下:
10
3.14
hello
int
float64
string
由于在Go语言中,你定义的变量必须都要使用,如果定义了但不用就会报错。但有些变量后面确实不用,就可以使用匿名变量。
_:匿名变量,丢弃数据不进行处理,匿名变量配合函数返回值使用才有价值
func main() {
//匿名变量
//_匿名变量 在后面学习中涉及到函数多个返回值时 使用匿名变量
a, _, _ := 10, 20, 30
fmt.Println(a)
//fmt.Println(_)//error 匿名变量数据不能打印
}
2.6 数据交换
变量名1,变量名2 = 变量名2,变量名1
这里根Python里是一样的。
具体如下:
package main
import "fmt"
func main() {
a := 10
b := 20
a, b = b, a
fmt.Println(a)
fmt.Println(b)
}
结果如下:
20
10
2.7 输出格式
根据前面的内容,我们看到了三种输出方式:
fmt.Println("hello"):输出换行
fmt.Print("hello"):输出不换行
fmt.Printf("%s ", "hello"):格式化输出,也不换行
具体如下:
func main() {
//打印并换行
fmt.Println("hello")
//打印但不换行
fmt.Print("hello")
fmt.Print("world")
}
结果如下:
hello
helloworld
func main() {
a, b, c := 3, 4.1426, "你瞅啥"
//
是一个占位符,表示输出换行
fmt.Printf("%d
", a)
fmt.Printf("%.3f
", b)
fmt.Printf("%s
", c)
}
结果如下:
3
4.143
你瞅啥
2.8 输入格式
前面我们所写的所有的程序,都是直接给变量赋值,但是很多情况下,我们希望用户通过键盘输入一个数值,存储到某个变量中,然后将该变量的值取出来,进行操作。我们日常生活中也经常用到输入的场景:
咱们在银行ATM机器前取钱时,肯定需要输入密码,对不?
那么怎样才能让程序知道咱们刚刚输入的是什么呢??
大家应该知道了,如果要完成ATM机取钱这件事情,需要先从键盘中输入一个数据,然后用一个变量来保存,是不是很好理解啊!
那么我们Go语言怎样接收用户的键盘输入呢?如下:
func main() {
var username string
var passwd string
fmt.Print("用户名:")
fmt.Scanf("%s", &username)
fmt.Print("密码:")
fmt.Scanf("%s", &passwd)
fmt.Println(username)
fmt.Println(passwd)
}
在Go中我们用到了“fmt”这个包中的Scanf()函数来接收用户键盘输入的数据。当程序执行到Scanf()函数后,会停止往下执行,等待用户的输入,输入完成后程序继续往下执行。在这里重点要注意的是Scanf()函数的书写格式,首先也要用“%s”,来表示输入的是一个字符串,输入完整数后存储到变量username中,注意这里username,变量前面一定要加上“&”符号,表示获取内存单元的地址(前面我们说的内存存储区域的编号),然后才能够存储。
还有另外一种获取用户输入数据的方式,如下
func main() {
var a int
//&,取地址运算符 引用运算符
//fmt.Scan是一个阻塞时的请求
fmt.Scan(&a)
fmt.Println(a)
//取出变量对应的内存地址
fmt.Println(&a)
fmt.Printf("%p
", &a)
}
通过Scan函数接收用户输入,这时可以省略掉%d,这种写法更简单。
三.基本数据类型
前面我们写的程序中,用到的变量的类型都是整型,但是在我们GO语言中,还有很多其它的类型。
类型 |
名称 |
长度 |
零值 |
说明 |
bool |
布尔类型 |
1 |
false |
其值不为真即为假,不可以用数字代表true或false |
byte |
字节型 |
1 |
0 |
uint8别名 |
int, uint |
整型 |
- |
0 |
有符号32位或无符号64位 |
int8 |
整型 |
1 |
0 |
-128 ~ 127 |
uint8 |
整型 |
1 |
0 |
0 ~ 255 |
int16 |
整型 |
2 |
0 |
-32768 ~ 32767, |
uint16 |
整型 |
2 |
0 |
0 ~ 65535 |
int32 |
整型 |
4 |
0 |
-2147483648 到 2147483647 |
uint32 |
整型 |
4 |
0 |
0 到 4294967295(42亿) |
int64 |
整型 |
8 |
0 |
-9223372036854775808到92233720368547758070 |
uint64 |
整型 |
8 |
0 |
到 18446744073709551615(1844京) |
float32 |
浮点型 |
4 |
0.0 |
小数位精确到7位 |
float64 |
浮点型 |
8 |
0.0 |
小数位精确到15位 |
string |
字符串 |
|
"" |
utf-8字符串 |
3.1 布尔类型
在计算机中,我们用什么数据类型来表示一句话的对错,例如:在计算机中描述张三(20岁)比李四(18)小,这句话的结果?
布尔类型的变量取值要么是真(true),要么是假(false),用bool关键字来进行定义。示例如下:
func main() {
//var a bool
//a = true
a := true
fmt.Println(a)
fmt.Printf("%T
", a)
//%t 是一个占位符,表示输出一个布尔类型的数据
fmt.Printf("%t
", a)
}
结果如下:
true
bool
true
布尔类型主要用于条件判断
3.2 整型
func main() { var a int = -127 //uint,表示无符号整型数据,只能存储大于0的整数 var b uint = 128 fmt.Println("a:", a) fmt.Println("b:", b) }
结果如下:
a: -127
b: 128
当一个整形数据达到了区间的最值时,再进行操作时就会发生变化
var a int8 = -128
var b int8 = 127
a -= 1
b += 1
//数据溢出
//如果数据达到了区间的最值时,再操作就会发生变化(物极必反)
fmt.Printf("a:%d
", a)
fmt.Printf("b:%d
", b)
结果如下:
a:127 b:-128
3.3 浮点型
浮点型就是小数类型,在Go中分为分float32和float64两种浮点型,用float64就可以。通过自动推导类型创建的浮点型数据 ,数据类型就是float64。
func main() {
//单精度浮点型,小数位数有效为7位
var a float32 = 3.44
//双精度浮点型,小数位数有效为15位
var b float64 = 3.44
//建议在开发中使用float64代替float32
//自动推导类型创建浮点型,默认为float64
c := 3.14
fmt.Println(a)
fmt.Println(b)
fmt.Printf("%T
", c)
fmt.Printf("%.20f
", a)
fmt.Printf("%.20f
", b)
}
结果如下:
3.44
3.44
float64
3.44000005722045898438
3.43999999999999994671
3.4字符类型
所谓字符类型是用单引号括起来的单个字符,关于字符的定义使用如下:
func main() {
//var 变量名 byte = '',字符用''表示,字符串用""表示
//每个字符都对应有一个ACSII值
var ch byte = 'a'
var ch2 byte = 97
//转义字符
var xh byte = 'v'
//在使用fmt.Println输出一个字符时,会得到对应的ACSII值
fmt.Println(ch)
fmt.Println(ch2)
fmt.Println(xh)
//%c,是一个占位符,表示一个字符,想要输出字符时,需要用fmt.Printf
fmt.Printf("%c
", ch)
fmt.Printf("%c
", ch)
}
结果如下:
97
97
11
a
a
这里定义了,ch是一个字符类型,赋值却是一个整数97,打印的结果是小写字符’a’。
原因是:计算机不能直接存储字符类型,只能转成数字存储,但是为什么小写字符‘a’,对应的整数是97呢?因为,计算机是根据’ASCII’码来存储。
附:转义字符:
字符除了我们常见的字符‘a’,字符’b’等等以外,还有一些特殊的字符,例如前面用到的’ ’, 它的作用是什么?换行,不会在屏幕上输出具体的内容。这种字符我们称为转义字符(具有特殊含义),那么除了’ ’字符以外,还有哪些是我们以后编程中经常用到的转义字符呢?
":表示一个英文半角的双引号
:表示一个tab键的空格(可以用来对输出的内容进行排版)
\:表示一个(主要用在表示磁盘目录上,后面学到文件操作时,经常要根据磁盘目录获取文件然后进行读取,写入等操作)
3.5 字符串类型
用单引号括起来的单个字符是字符类型,用双引号括起来的字符是字符串类型。
字符串的定义如下:
func main() {
//var a string = "h"
a := "h"
fmt.Println(a)
//%s 是一个占位符,表示输出一个字符串类型的变量
fmt.Printf("%s
", a)
//%T 是一个占位符,表示输出一个变量的数据类型
fmt.Printf("%T
", a)
}
结果如下:
h h string
字符串的拼接和比较如下(算术运算符和关系运算符会在后面讲到),两个字符串相加表示的是字符串拼接:
func main() {
str1 := "大哥"
str2 := "你好"
//字符串拼接
fmt.Println(str1 + str2)
//字符串比较
fmt.Println(str1 == str2)
}
结果如下:
大哥你好
false
3.6 字符串和字符的关系
用单引号括起来的单个字符是字符类型,用双引号括起来的字符是字符串类型。
具体关系由下方代码进行展示:
func main() {
ch := 'a'
//字符串"a"存储了两个字符:'a'和' '( 是一个转义字符,表示字符串的结束标示)
str := "a"
fmt.Println(ch)
fmt.Println(str)
//一个字符如果不想输出ASCII值,就需要用 %c 占位符
fmt.Printf("%c
", ch)
fmt.Printf("%s
", str)
str1 := "你好"
//len():计算字符串中字符的个数, 之前的字符是有效字符
//在go语言中,一个汉字占3个字符
fmt.Println(len(str))
fmt.Println(len(str1))
}
结果如下:
97
a
a
a
1
6
3.7 占位符的使用
我们前面在输出与输入字符串类型,字符类型,整型等都指定了对应的格式化,那么go语言中还有哪些格式化呢?
格式 |
含义 |
%% |
一个%字面量 |
%b |
一个二进制整数值(基数为2),或者是一个(高级的)用科学计数法表示的指数为2的浮点数 |
%c |
字符型。可以把输入的数字按照ASCII码相应转换为对应的字符 |
%d |
一个十进制数值(基数为10) |
%f |
以标准记数法表示的浮点数或者复数值 |
%o |
一个以八进制表示的数字(基数为8) |
%p |
以十六进制(基数为16)表示的一个值的地址,前缀为0x,字母使用小写的a-f表示 |
%q |
使用Go语法以及必须时使用转义,以双引号括起来的字符串或者字节切片[]byte,或者是以单引号括起来的数字 |
%s |
字符串。输出字符串中的字符直至字符串中的空字符(字符串以' ‘结尾,这个' '即空字符) |
%t |
以true或者false输出的布尔值 |
%T |
使用Go语法输出的值的类型 |
%x |
以十六进制表示的整型值(基数为十六),数字a-f使用小写表示 |
%X |
以十六进制表示的整型值(基数为十六),数字A-F使用小写表示 |
整型占位符代码如下:
//int
func main1401() {
//%%,表示字面%
fmt.Printf("35%%
")
a := 123
//%b,表示输出一个数的二进制格式(0-1)
fmt.Printf("%b
", a)
//%o,表示输出一个数的八进制格式(0-7)
fmt.Printf("%o
", a)
//%x %X,表示输出一个数的十六进制(0-9,Aa-Ff)
fmt.Printf("%x
", a)
fmt.Printf("%X
", a)
//%d,表示输出一个数的十进制格式
//%nd,整体数据为n位,如果不足n位则在前面补空格
//%-nd,整体数据为n位,如果不足n位则在后面补空格
//%0nd,整体数据为n位,如果不足n位则在前面补上0
fmt.Printf("===%d===
", a)
fmt.Printf("===%5d===
", a)
fmt.Printf("===%-5d===
", a)
fmt.Printf("===%05d===
", a)
}
结果如下:
35%
1111011
173
7b
7B
===123===
=== 123===
===123 ===
===00123===
浮点型占位符代码如下:
//float
func main1402() {
a := 3.1415926
//%f,是一个占位符,表示输出一个浮点型数据,默认保留6位有效数字,会四舍五入
//%.nf,表示小数点后保留n位,会对n+1位进行四舍五入
//%m.nf,表示整体数据为m位,小数点后保留n位,.占一位,如果不足m位则在前面补空格
fmt.Printf("%f
", a)
fmt.Printf("%.2f
", a)
fmt.Printf("%6.3f
", a)
}
结果如下:
3.141593
3.14
3.142
字符和字符串占位符代码如下:
//byte和string
func main() {
ch := 'a'
str := "a"
//一个字符想要输出字符格式,就需要用 %c 占位符,否则就会输出对应的ASCII值
fmt.Printf("%c
", ch)
fmt.Printf("%s
", str)
//%q,是一个占位符,表示输出带双引号的字符串或字符切片
fmt.Printf("%q
", str)
}
结果如下:
a
a
"a"
布尔类型和数据类型代码如下:
//bool和变量的数据类型
func main() {
a := true
fmt.Printf("%t
", a)
fmt.Printf("%T
", a)
//%p,是一个占位符,表示输出一个数据对应的内存地址
//&:取地址符,可以得到变量对应的内存地址
fmt.Printf("%p
", &a)
}
结果如下:
true
bool
0xc000016048