本文最后更新于 709 天前,其中的信息可能已经有所发展或是发生改变。
近段时间,本人开始无基础入门 Go 语言,既是为毕设打基础,更是为日后的社会工作做准备。
由此,不定期更新近期学习中的收获,供学习交流用。
本篇中,将简单介绍 Go 语言最基础的知识:变量与常量,数据类型,运算符,条件和循环。
Hello world!
不解释,直接放出代码:
package main
import "fmt"
func main() {
fmt.Println("Hello world!")
}
变量与常量
变量
Go 中的变量需要声明以后才能且必须使用,同一作用域内不支持重复声明。
常用的声明变量方式:
//var indertifer type
var age int //int类型的变量不赋值,默认值是0
var price float64 = 5 //声明变量为64位浮点,且赋值5
var flag bool //默认值是false
var (
a int = 1
b int = 1
)
可以同时声明多个变量:
var x, y int
var a, b = 24, "years"
特别的,Go 支持类型推断:
var title = “Tempest”
var count = 10
短变量只能在函数内部进行声明,使用 :=
运算符对变量进行声明和初始化。
mystr := "hello world"
特别注意,在以下代码中:
mystr := "hello world"
mystr := "hello"
会出现编译错误。:=仅用于对变量的声明,而同一个变量名不能声明两次。
故第二行的:=不符合规范,应使用=符号进行赋值操作。
*若使用:=声明多个变量,则仅需其中至少一个为新变量即可,如:
mystr,anostr := "hello","world"
则不会报编译错误,因为anostr为新变量声明。但你不能通过此方法改变mystr的变量类型。
:= 不能被用在函数体外,也就是说,当你打算声明一个全局变量时,你只能使用var。
如果我们接收到多个变量,有一些变量使用不到,可以使用下划线作为变量名,这种变量叫做匿名变量。
func GetInteger() (int, int) {
return 1, 2
}
x, _ := GetInteger()
_, y := GetInteger()
fmt.Println(a, b) //输出结果为 1 2
常量
定义一个常量使用 const,语法如下:
//const constantName [type] = value
const PI float32 = 3.14
const H = 100
const (
a int = 1
b = 2
c //如不指定类型和初始化值,则与上一行非空常量右值相同
)
iota是go语言的常量计数器,只能在常量表达式中使用。
iota在const关键字出现时将被重置为0,const中每新增一行常量声明将使iota计数一次。
const (
a = iota //0
b = iota //1
c = iota //2
)
const ( //iota中间截断
d = iota //0
e = 114514
f = iota //2
)
const (
g = iota //0
_ //1
h = iota //2
)
数据类型
基本数据类型如下:
- 整型
- 有符号:
int8 int16 int32 int64
rune
是int32
的别名类型。int16
对应 C 语言中的short
型 ,int64
对应 C 语言中的long
型。int
自动匹配所用的操作系统,系统是 32 位就是int32
,系统是 64 位就是int64
。
- 无符号:
uint8 uint16 uint32 uint64
byte
是uint8
的别名类型。
- 有符号:
- 浮点型(遵循
IEEE 754
标准)float32
最大范围为3.4e38
,用常量math.MaxFloat32
float64
最大范围为1.8e308
,用常量math.MaxFloat64
- 复数
complex64
实部和虚部分别是 32 位complex128
实部和虚部分别是 64 位
- 布尔值
bool
:只有true
和false
- 字符串
string
内部实现使用 UTF-8 编码- 多行字符串,用反引号(“)。
反引号间换行认为字符串中的换行;但是反引号间所有的转义字符均无效。
- 多行字符串,用反引号(“)。
运算符
Go 的基础运算符如下:
首先定义:
var (
a,b,c int = 10,20,5 //1010,10100,101
d,e bool = true,false
)
则相应的运算符与结果如下:
算术运算符
算术运算符 | 描述 | 运算结果 |
+ | 相加 | a + b 结果为 30 |
– | 相减 | a – b 结果为 -10 |
* | 相乘 | a * b 结果为 200 |
/ | 相除 | b / a 结果为 2 |
% | 取余 | a % b 结果为 10 |
++ | 自增 | a++ 结果为 11 |
— | 自减 | b– 结果为 19 |
++a
,--b
)赋值运算符
赋值运算符 | 描述 | 运算结果 |
= | 将一个表达式的值赋给一个左值 | c = a + b,c 为 30 |
+= | 相加后赋值 | c += a,c 为 15 |
-= | 相减后赋值 | c -= b,c 为 -15 |
*= | 相乘后赋值 | c *= a,c 为 50 |
/= | 相除后赋值 | b /= a,b 为 2 |
%= | 左移后赋值 | a %= c,a 为 0 |
<<= | 左移后赋值 | a <<= c,a 为 320 |
关系运算符
关系运算符 | 描述 | 运算结果 |
== | 检查是否相等 | a == b 为 false |
!= | 检查是否不相等 | a != b 为 true |
> | 检查左值是否大于右值 | a > b 为 false |
< | 检查左值是否校于右值 | a < b 为 true |
>= | 检查左值是否大于等于右值 | a >= b 为 false |
<= | 检查左值是否小于等于右值 | a <= b 为 true |
逻辑运算符
逻辑运算符 | 描述 | 运算结果 |
&& | 逻辑 AND | d && e 为 false |
|| | 逻辑 OR | d || e 为 true |
! | 逻辑 NOT | !e 为 true |
位运算符
位运算符 | 描述 | 运算结果 |
& | 二进制各位相与 | a & b 为 0 |
| | 二进制各位相或 | a | b 为 30 |
^ | 二进制各位相异或 | a ^ b 为 30 |
<< | 左移运算 | a << 2 为 40 |
>> | 右移运算 | b >> 2 为 5 |
&^ | 按位清零 | a &^ b 为 10 |
其他运算符
运算符 | 描述 | 运算结果 |
& | 对变量取地址 | &a 返回变量的实际内存地址 |
* | 对地址取值 | *a 返回指针变量对应的数值 |
下面用一段代码来举例:
package operator_test
import "testing"
func TestComapreArray(t *testing.T) {
a := [...]int{1, 2, 3, 4}
b := [...]int{1, 3, 4, 5}
//c := [...]int{1, 2, 3, 4, 5}
d := [...]int{1, 2, 3, 4}
t.Log(a == b)
//t.Log(a==c)
t.Log(a == d)
}
const (
read int = 4
write int = 2
exec int = 1
)
func TestBitClear(t *testing.T) {
var a int = 7
a = a &^ write
t.Log(a, a&read == read, a&write == write, a&exec == exec)
}
其测试结果如下:
=== RUN TestComapreArray
operator_test.go:10: false
operator_test.go:12: true
--- PASS: TestComapreArray (0.00s)
=== RUN TestBitClear
operator_test.go:24: 5 true false true
--- PASS: TestBitClear (0.00s)
PASS
Process finished with the exit code 0
测试结果解析:
- TestComapreArray 函数中,a,b,c,d 为四个数组
- a 与 b 内部数据不同,故其不相等,返回 false
若b := [...]int{1, 3, 2, 4}
因其顺序不相同,仍然返回 false - a 与 c 数组长度不相同,若强行进行比对会报编译错误,提示变量类型不同
- a 与 d 数组长度相同,内部数据也相同,故返回 true
- a 与 b 内部数据不同,故其不相等,返回 false
- TestBitClear 函数中,模拟了文件读写权限的运算
- 0111 代表可读写,可执行,
var a int = 7
对其赋对应值 a = a &^ write
,即对其取消写入权限,此时 a=5 ,对应二进制 0101- 最后进行比对,可知 a=5,对应可读可执行不可写,与前面按位清零运算对应
- 0111 代表可读写,可执行,
条件和循环
条件
if … else 语句
if 语句遵循如下格式:
if condition1 {
// do something
} else if condition2 {
// do something else
} else {
// catch-all or default
}
switch语句
在 Go 语言中,switch 语句会与其他语言有所不同:
switch
语句找到匹配项执行完毕后,默认不需要 break 即跳出语句。switch
默认情况下case
最后自带break
语句,匹配成功后就不会执行其他case
,如果我们需要执行后面的case
,可以使用fallthrough
。switch
后面变量的类型可以是任何类型,不再局限于常量或整数。
示例代码如下:
func TestSwitchCondition(t *testing.T) {
for i := 1; i <= 12; i++ {
switch i {
case 1, 3, 5, 7, 9:
t.Log("odd")
case 2, 4, 6, 8, 10:
t.Log("even")
default:
t.Log("too high")
}
}
}
循环
与 C++ 等其他语言不同,Go 对于循环只有 for
语句,并没有其他语言常用的 while
和 do-while
等。
package loop
import "testing"
func TestWileLoop(t *testing.T) {
for i := 1; i <= 5; i++ {
t.Log(i, i%2 == 0) //从1-5整数顺序输出,并判定是否偶数
}
}
如上述代码,Go 的 for
语句与其他语言并没有太大不同。其使用遵循以下格式:
for init; condition; post {
// body
}