一、Go语言程序元素
1、标识符
Go语言标识是用于标示变量、函数或任何用户自定义项目的名称(程序实体)。标识符又两种类别,一种是用户定义的标识符,它作为程序实体存在,一般来说同一个代码块中不许程序实体同名,使用不同代码包中的实体需要使用包表示符声明;另一种标识符称为预定义标识符,它们在Go语言源代码中声明。
标识符以字母a~z(大小写均可)或下划线 _ 开头,后面可以是多个字母、下划线和数字。Go语言不允许在标识符中使用标点符号,例如@、$、%等一系列符号。
2、关键字
Go语言作为一门静态编译型语言,它的关键字一共有25个,相比其他编程语言来说显得非常少,因此某种意义上也就更简单了。下面是Go的25个关键字:
- 包导入与声明:
import
、package
- 程序实体声明与定义:
var
、type
、func
、interface
、map
、struct
、chan
、const
- 流程控制:
if
、continue
、for
、return
、go
、case
、goto
、switch
、select
、else
、break
、default
、defer
、fallthrough
、range
上面显示的Go的关键字,也称为保留字,这些保留字不能用作常量、变量或任何其他标识符名称。除此之外,还有一个比较特殊的类型叫做空接口,它的字面量是_
(下划线)。
3、字面量
字面量就是表示值的一种标记法,但是在Go语言中,字面量的含义要广一些。首先,它用于表示基础数据类型值的各种字面量;其次用于表示用户构造的自定义符合数据类型的类型字面量;最后它还用于表示符合数据类型的值的复合字面量,简单来说,它会被用来构造类型Struct
(结构体)、Array
(数组)、Sli
(切片)和Map
(字典)的值。
- 举例说明
原文链接:https://www.dqzboy.com :
const b int = 10 //定义了一个常量b,类型为int,b的值为10,而这个10又称为字面量
var str string = "hello world" //定义了一个变量str,类型为string,值为hello world,而这个hello world就是字面量
4、分隔符
分隔符用于分隔其他元素。程序代码都是通过语句来实现结构化的,但是Go语言不需要以分号 ;
结尾,这些工作由Go语言编译器自动完成。但是,如果将多个语句写在同一行,它们必须使用 ;
分号分隔,实际开发中不鼓励这种写法。
5、运算符
运算符是用于执行运算或逻辑操作的符合。Go语言的运算符如下:
运算符 | 说明 |
|| | 或,二元逻辑运算符,例如 true || false返回true |
&& | 与,二元逻辑运算符, 例如 true && false返回false |
! | 非, 二元逻辑运算符 |
== | 相等判断, 二元逻辑运算符 |
!= | 不等判断,二元逻辑运算符 |
< | 小于判断,二元逻辑运算符 |
<= | 小于等于判断, 二元逻辑运算符 |
> | 大于判断,二元逻辑运算符 |
>= | 大于等于判断, 二元逻辑运算符 |
+ | 求和操作,二元算术运算符 |
– | 求差操作,二元算术运算符 |
* | 乘积操作,二元算术运算符 |
/ | 求商操作,二元算术运算符 |
| | 按位或操作, 二元算术运算符 |
^ | 按位异或操作, 二元算术运算符 |
% | 求余操作,二元算术运算符 |
<< | 按位左移操作,二元算术运算符 |
>> | 按位左移操作,二元算术运算符 |
& | 按位与操作,二元算术运算符 |
&^ | 按位清除操作,二元算术运算符 |
- 当一个表达式中有多个运算符时,就会遇到优先级的问题,在Go语言中,一元运算符的优先级高于二元运算符,二元运算符的优先级如下:
运算符 | 优先级 |
* 、 / 、 % 、 <<、 >>、 &、 &^、 | 最高 |
+、 -、 |、 ^、 | 较高 |
==、 !=、 <、 <=、 >、 >=、 | 中 |
&& | 较低 |
|| | 最低 |
- 如果一个表达式中出现优先级的运算符,那么根据从左到右的顺序依次操作。注意,所有运算符都受括号的影响,括号内先操作,在Go语言中,
++
和--
是语句,不是表达式,没有运算优先级之说。 - Go语言不支持运算符重载
6、注释
Go语言编译器遇到注释会完全忽略。注释是源代码中最重要的组成部分之一,注释的用途非常广泛,例
package main
import "fmt"
/*
下面定义了一个main函数,这是程序的入口
这段是块注释
*/
func main() {
fmt.Println("我爱中国") //这是行注释,打印输出语句 ”我爱中国”
}
二、Go语言的基本概念
1、常量
1.1:数字表示
Go语言的常量可以是十进制、八进制和十六进制常数;
- 前缀是
0x
或者0X
为十六进制 - 前缀是
0
的为八进制 - 十进制无前缀
整数还可以有一个后缀,它是U和L的组合,分别用于表示unsigned和long。后缀可以是大小写字母,顺序也是任意的。示例如下:
3.14 //十进制,合法
0213 //八进制,合法
0x4b //十六进制,合法
0xFeeL //合法
30u //无符号整型,合法
30l //long, 合法
30ul //无符号 long, 合法
078 //非法 :8 is not an octal digit
032UU //非法 :cannot repeat a suffix
1.2:转义表示
与其他语言语言,Go语言使用反斜杠表示转义符号,例如换行符(\n)
或制表符(\t)
转义序列 | 含义 |
\\ | \ 字符 |
\’ | ‘ 字符 |
\” | ” 字符 |
\? | ? 字符 |
\b | 退格 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
package main
import "fmt"
func main() {
fmt.Println("hello\tworld!")
fmt.Println("hello\nworld!")
}
#执行
$ go run Escape.go
hello world!
hello
world!
1.3:赋值
- Go语言支持以下赋值运算符:
package main
import "fmt"
func main() {
a := 20
c := 200
c = a
fmt.Println("赋值操作,把a的值赋值给c,所以c的值为:",c) //现在c的值为20
c += a
fmt.Println("相加和赋值运算符,实际为c = c + a,所以c的值为:",c) //在上面c的值为20的基础上在加a的值,所以现在c的值为40
c -= a
fmt.Println("相减和赋值运算符,实际为c = c - a,所以c的值为:",c) //在上面c的值为40的基础上减去a的值,所以现在c的值为20
c *= a
fmt.Println("相乘和赋值运算符,实际为c = c * a,所以c的值为:",c) //在上面c的值为20的基础上乘以a的值,所以现在c的值为400
c /= a
fmt.Println("相除和赋值运算符,实际为c = c / a,所以c的值为:",c) //在上面c的值为400的基础上除以a的值,所以现在c的值为20
c <<= a
fmt.Println("左移和赋值运算符,所以c的值为:",c)
c >>= a
fmt.Println("右移和赋值运算符,所以c的值为:",c)
c &= a
fmt.Println("按位与和赋值运算符,所以c的值为:",c)
c ^= a
fmt.Println("按位异和赋值运算符,所以c的值为:",c)
c |= a
fmt.Println("按位或和赋值运算符,所以c的值为:",c)
}
#返回结果为:
$ go run assignment.go
赋值操作,把a的值赋值给c,所以c的值为: 20
相加和赋值运算符,实际为c = c + a,所以c的值为: 40
相减和赋值运算符,实际为c = c - a,所以c的值为: 20
相乘和赋值运算符,实际为c = c * a,所以c的值为: 400
相除和赋值运算符,实际为c = c / a,所以c的值为: 20
左移和赋值运算符,所以c的值为: 20971520
右移和赋值运算符,所以c的值为: 20
按位与和赋值运算符,所以c的值为: 20
按位异和赋值运算符,所以c的值为: 0
按位或和赋值运算符,所以c的值为: 20
1.3:枚举
- 常量还可以用作枚举:
package main
import "fmt"
const (
a = iota //返回0
b //返回1,隐式使用iota关键字,实际等同于 b = iota + 1
c //返回2
d,e,f = iota,iota,iota //d==3,e==3,f==3,同一行值相同,此处多个常量则iota也必须对应有几个
g = iota //g==4
h = "h" //h=="h"
i //i==6
j = iota //j==7
)
const z = iota //每个单独定义的const常量中,iota都会重置,此时z == 0
func main() {
fmt.Println(a,b,c,d,e,f,g,h,i,j)
}
- 每个
const
定义的第一个常量被默认设置为0,显式设置了值的常量除外。
2、变量
2.1:变量的声明
变量是Go语言中表示抽象和储存计算结果的一种概念。变量的值通过变量名访问,Go语言的变量名命名规则与常量名一样,都是由字母、数字、下划线组成的,其中名称首个字母不能为数字等。
变量的声明格式是:var 名称 类型,也就是使用var
关键字。Go语言和其他大部分编程语言不同的一个地方,就是它在声明变量时将变量的类型放在变量的名称后面。这样语法从左到右的顺序阅读,更符合人类的语言习惯。
//定义一个变量a为int类型
var a int
//定义一个变量b为bool类型
var b bool
//定义一个变量str为string类型
var str string
//定义两个个变量a、b为int类型
var a, b int
//也可以写到一块
var (
a ,b int
c bool
str string
)
//同一个类型的多个变量可以声明在同一行
var a, b, c int
//多变量可以在同一行进行声明和赋值
var a, b, c int = 1, 2, 3
//多变量可以在同一行进行赋值(下面的方式只能在函数体内赋值)
func variable() {
a, b = 1, 2
}
2.2:局部变量声明
a := 1 //等同于 var a = 1
- Go语言编译器会智能推断类型,此处不写 a 变量的类型也是因为Go语言编译器会自动根据值推断出a的类型。
- Go语言官方推荐使用这种方式定义变量,但是必须注意,它只能被用在函数体内,不可以用于全局变量的声明和赋值,如下示例:
package main
import "fmt"
/*
在全局以这种方式定义变量是错误的,执行会报如下错:
syntax error: non-declaration statement outside function body
*/
//a := 1
//全局定义必须使用var关键字定义
var a = 1
/* 同一个代码块中不能重复定义同一个变量
执行会报错:a redeclared in this block
*/
//var a = 2
func main() {
b := 1 //在函数体内使用这种简短声明是没有问题的
a = 100 //把值赋值给a没有语法问题。注意:这里是给a赋值,而不是定义变量,定义变量需要在等号前面加冒号:
fmt.Println(a)
a := "hello" //上面全局定义的var 定义a变量属于一个代码块,这里是函数体里面是另外一个代码块,可以再次声明a,改变变量类型
fmt.Println(a,b,c) //注意:这里的c调用的是全局变量,并且全局定义的变量不限制位置。结果:hello 1 50
//不能在调用函数之后定义变量
//fmt.Println(d) //先调用后定义,这个是错误的
//d := 4
}
//全局定义的变量不限定位置,在函数之外即可,在函数之内不可以
var c = 50
/*
输出结果:
100
hello 1 50
*/
使用 :=
可以快速创建一个函数内部的变量,它包括初始化声明与赋值两大部分。注意以下几点:
- 同一个代码块内不能多次声明同一个变量(上面示例中的 var a)
- 函数内部可以使用全局定义的变量并重新赋值(上面示例中 a = 100)
- 函数体内属于独立的代码块,可以重新进行声明变量(上面示例中的 a := “hello” ),可以改变变量类型,并且定义只在函数体内部生效
- 如果在定义变量之前就先调用了该变量,那么会编译错误,返回undefined(上面示例中的变量d)
- 全局定义不限制位置,但建议统一放在函数代码前面(上面示例中的 var c = 50)
2.3:匿名变量
全局变量自然就是全局可用,局部变量只能在相应的代码块内起作用,除此之外,局部变量还有一个特点就是,定义的必须使用(全局变量允许声明但不使用)。如果定了局部变量,但是却没有在这个代码块中调用这个局部变量,那么编译也会出现错误,例如:
package main
import "fmt"
func main() {
a := "hello"
fmt.Println("hello world")
}
//输出结果报错: a declared but not used
- 所以这里的要求是要被使用,即使是赋值了也会出现报错,这个值必须被使用,例如打印出来,或者赋值给其他变量
- 在使用强类型语言编程时,经常会出现在调用函数时,该函数返回多个值,其中只有一个值是需要的时候的情况,这个时候就可以使用空标识符来解决这个问题,例如
_=a
,这样就不会报错了,这种写法可以忽略一些多返回值的函数的部分返回值。
2.4:init函数
Go语言中,除了可以在init
函数中初始化。init
函数是一个特殊的函数,它会在包完成初始化后自动执行,执行优先级比main函数高,并且不能手动调用init函数。每一个源文件有且只有一个init函数,初始化过程会根据包的依赖关系按顺序单线程执行。
可以在开始执行之前通过这个函数来对数据进行检验和修复,保证程序执行时状态。例如:
package main
import (
"fmt"
"math"
)
//Pi为圆周率
var Pi float64
func init() {
Pi = 4* math.Atan(1) //在init函数中计算Pi的值
}
func main() {
DPi := Pi * Pi
fmt.Println(Pi, DPi) //结果:3.141592653589793 9.869604401089358
}
必须 注册 为本站用户, 登录 后才可以发表评论!