GoLang基础

@TOC

第一个Go程序-hello,world!

国际惯例,编写第一个程序,首先打印“hello,world!”。

1
2
3
4
5
6
7
package main

import "fmt"

func main(){
fmt.Println("hello,world!")
}

程序基本结构:

1
2
3
4
5
6
package //包声明

import //包导入

func main(){ //入口函数
}

OK,一行一行来。

  • package关键字定义一个叫main 的包,main包是个特殊的包,程序的入口就在这个包。
  • import关键字用来导入程序中使用到的外部包。
  • func 是用来声明函数的,main函数是程序的入口函数。
  • fmt是go内置的一个包,fmt.println()函数打印输出并在末尾自动换行。

变量和常量

标识符和关键字

标识符

  • 在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名、常量名、函数名等等。 Go语言中标识符由字母数字和_(下划线)组成,并且只能以字母和_开头。举个栗子,_a123, abc, a_4等等。

关键字

  • 关键字是指编程语言中预先定义好的具有特殊含义的标识符。 关键字和保留字都不建议用作变量名。
  • Go语言中有25个关键字:
1
2
3
4
5
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
  • 此外,Go语言中还有37个保留字。
1
2
3
4
5
6
7
8
9
10
Constants:    true  false  iota  nil

Types: int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64 complex128 complex64
bool byte rune string error

Functions: make len cap new append copy close delete
complex real imag
panic recover

变量的来历

程序运行过程中的数据都是保存在内存中,我们想要在代码中操作某个数据时就需要去内存上找到这个变量,但是如果我们直接在代码中通过内存地址去操作变量的话,代码的可读性会非常差而且还容易出错,所以我们就利用变量将这个数据的内存地址保存起来,以后直接通过这个变量就能找到内存上对应的数据了。

变量(Variable)的功能是存储数据。不同的变量保存的数据类型可能会不一样。经过半个多世纪的发展,编程语言已经基本形成了一套固定的类型,常见变量的数据类型有:整型、浮点型、布尔型等。

Go语言中的每一个变量都有自己的类型,并且变量必须经过声明才能开始使用。

声明变量

  • 变量的标准声明方式:
1
var 变量名 变量类型
  • 变量声明以关键字var开头,变量类型放在变量的后面,行尾无需分号。
1
2
var age int
var name string
  • 批量声明

  • 每次声明变量都要写var关键字十分繁琐,Go还支持变量的批量声明:

1
2
3
4
var (
age int
name string
)

初始化变量

Go语言在声明变量时,自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型的默认值,例如:

  • 整型和浮点型变量的默认值为0。
  • 字符串变量的默认值为空字符串。
  • 布尔型变量默认值为false。
  • 切片、函数、指针变量的默认值为nil。
    当然,我们依然可以在变量声明时赋予变量一个初始值。
  1. 标准格式
1
var 变量名 变量类型 = 表达式

栗子:

1
var hp int = 100
  1. 编译器推导类型
    在标准格式的基础上,将int省略后,编译器会尝试根据等号右边的表达式推导hp变量的类型。
1
var hp = 100

举一堆栗子:

1
2
3
4
5
var attack = 40
var defence = 20
var damageRate float32 = 0.17
var damage = float32(attack -defence) * damageRate
fmt.Println(damage)

  1. 短变量声明及初始化
    一种更为简洁的写法,在开发中使用比较普遍。
1
hp := 10

如果hp已经被声明过,但依然使用“:=”时编译器会报错。

1
2
3
4
//声明hp变量
var hp int
//再次声明并赋值
hp := 10

编译报错如下:

1
no new variables on left side of :=

匿名变量

在使用多重复值时,若果不需要再左值中接收变量,可以使用匿名变量。
匿名变量用_(下划线)表示,使用时,只要在变量声明的地方使用下划线代替即可。

1
2
3
4
5
6
7
8
9
10
11
12
func GetData()(int, int){
return(200, 300)
}

a, _ = GetData()

_, b = GetData()

fmt.Println(a, b)

output:
200 300

常量和iota

相对于变量,常量是恒定不变的值,多用于定义程序运行期间不会改变的那些值。 常量的声明和变量声明非常类似,只是把var换成了const,常量在定义的时候必须赋值。

1
2
const pi = 3.1415
const e = 2.7182

声明了pi和e这两个常量之后,在整个程序运行期间它们的值都不能再发生变化了。

多个常量也可以一起声明:

1
2
3
4
const (
pi = 3.1415
e = 2.7182
)

const同时声明多个常量时,如果省略了值则表示和上面一行的值相同。 例如:

1
2
3
4
5
const (
n1 = 100
n2
n3
)

上面示例中,常量n1、n2、n3的值都是100。

iota

iota是go语言的常量计数器,只能在常量的表达式中使用。

iota在const关键字出现时将被重置为0。const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。 使用iota能简化定义,在定义枚举时很有用。

举个例子:

1
2
3
4
5
6
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)

几个常见的iota示例:

使用_跳过某些值

1
2
3
4
5
6
const (
n1 = iota //0
n2 //1
_
n4 //3
)

iota声明中间插队

1
2
3
4
5
6
7
const (
n1 = iota //0
n2 = 100 //100
n3 = iota //2
n4 //3
)
const n5 = iota //0

定义数量级 (这里的<<表示左移操作,1<<10表示将1的二进制表示向左移10位,也就是由1变成了10000000000,也就是十进制的1024。同理2<<2表示将2的二进制表示向左移2位,也就是由10变成了1000,也就是十进制的8。)

1
2
3
4
5
6
7
8
const (
_ = iota
KB = 1 << (10 * iota)
MB = 1 << (10 * iota)
GB = 1 << (10 * iota)
TB = 1 << (10 * iota)
PB = 1 << (10 * iota)
)

多个iota定义在一行

1
2
3
4
5
const (
a, b = iota + 1, iota + 2 //1,2
c, d //2,3
e, f //3,4
)

*摘抄自李文周的博客-Go语言基础之变量和常量

数据类型

整型

整型分为以下两个大类: 按长度分为:int8、int16、int32、int64 对应的无符号整型:uint8、uint16、uint32、uint64

其中,uint8就是我们熟知的byte型,int16对应C语言中的short型,int64对应C语言中的long型。

类型 描述
uint8 无符号 8位整型 (0 到 255)
uint16 无符号 16位整型 (0 到 65535)
uint32 无符号 32位整型 (0 到 4294967295)
uint64 无符号 64位整型 (0 到 18446744073709551615)
int8 有符号 8位整型 (-128 到 127)
int16 有符号 16位整型 (-32768 到 32767)
int32 有符号 32位整型 (-2147483648 到 2147483647)
int64 有符号 64位整型 (-9223372036854775808 到 9223372036854775807)

特殊整型

类型 描述
uint 32位操作系统上就是uint32,64位操作系统上就是uint64
int 32位操作系统上就是int32,64位操作系统上就是int64
uintptr 无符号整型,用于存放一个指针

浮点型

Go语言支持两种浮点型数:float32和float64。这两种浮点型数据格式遵循IEEE 754标准: float32 的浮点数的最大范围约为 3.4e38,可以使用常量定义:math.MaxFloat32。 float64 的浮点数的最大范围约为 1.8e308,可以使用一个常量定义:math.MaxFloat64。

复数

complex64和complex128。
复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位。

1
2
3
4
5
6
var c64 complex64
c64 = 2 + 3i
var c128 complex128
c128 = 4 + 5i
fmt.Println(c64)
fmt.Println(c128)

布尔型

Go语言中使用bool来声明布尔类型变量,布尔类型的值只有true和false两个值。

字符串

Go语言中的字符串以原生数据类型出现,使用字符串就像使用其他原生数据类型(int、bool、float32、float64 等)一样。 Go 语言里的字符串的内部实现使用UTF-8编码。 字符串的值为双引号(“)中的内容,可以在Go语言的源码中直接添加非ASCII码字符。

字符串转义符

转义符 含义
\r 回车符(返回行首)
\n 换行符(直接跳到下一行的同列位置)
\t 制表符
\’ 单引号
\” 双引号
\\ 反斜杠

字符串操作

方法 介绍
len(str) 求长度
+或fmt.Sprintf 拼接字符串
strings.Split 分割
strings.contains 判断是否包含
strings.HasPrefix,strings.HasSuffix 前缀/后缀判断
strings.Index(),strings.LastIndex() 子串出现的位置
strings.Join(a[]string, sep string) join操作

字符串修改以及类型转换

修改字符串

要修改字符串,需要先将其转换成[]rune或[]byte,完成后再转换为string。无论哪种转换,都会重新分配内存,并复制字节数组。

1
2
3
4
5
6
7
8
9
10
11
12
func changeString() {
s1 := "big"
// 强制类型转换
byteS1 := []byte(s1)
byteS1[0] = 'p'
fmt.Println(string(byteS1))

s2 := "白萝卜"
runeS2 := []rune(s2)
runeS2[0] = '红'
fmt.Println(string(runeS2))
}
类型转换

Go语言中只有强制类型转换,没有隐式类型转换。该语法只能在两个类型之间支持相互转换的时候使用。

强制类型转换的基本语法如下:

1
T(表达式)

其中,T表示要转换的类型。表达式包括变量、复杂算子和函数返回值等.

比如计算直角三角形的斜边长时使用math包的Sqrt()函数,该函数接收的是float64类型的参数,而变量a和b都是int类型的,这个时候就需要将a和b强制类型转换为float64类型。

1
2
3
4
5
6
7
func sqrtDemo() {
var a, b = 3, 4
var c int
// math.Sqrt()接收的参数是float64类型,需要强制转换
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(c)
}

运算符

算术运算符

运算符 描述
+ 相加
- 相减
* 相乘
/ 相除
% 求余
注意: ++(自增)和–(自减)在Go语言中是单独的语句,并不是运算符。

关系运算符

运算符 描述
== 检查两个值是否相等,如果相等返回 True 否则返回 False。
!= 检查两个值是否不相等,如果不相等返回 True 否则返回 False。
> 检查左边值是否大于右边值,如果是返回 True 否则返回 False。
>= 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。
< 检查左边值是否小于右边值,如果是返回 True 否则返回 False。
<= 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。

逻辑运算符

运算符 描述
&& 逻辑 AND 运算符。 如果两边的操作数都是 True,则为 True,否则为 False。
|| 逻辑 OR 运算符。 如果两边的操作数有一个 True,则为 True,否则为 False。
! 逻辑 NOT 运算符。 如果条件为 True,则为 False,否则为 True。

位运算符

运算符 描述
& 参与运算的两数各对应的二进位相与。(两位均为1才为1)
| 参与运算的两数各对应的二进位相或。(两位有一个为1就为1)
^ 参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1(两位不一样则为1)
<< 左移n位就是乘以2的n次方。“a << b”是把a的各二进位全部左移b位,高位丢弃,低位补0。
>> 右移n位就是除以2的n次方。“a>>b”是把a的各二进位全部右移b位。

赋值运算符

运算符 描述
= 简单的赋值运算符,将一个表达式的值赋给一个左值
+= 相加后再赋值
-= 相减后再赋值
*= 相乘后再赋值
/= 相除后再赋值
%= 求余后再赋值
<<= 左移后赋值
>>= 右移后赋值
&= 按位与后赋值
|= 按位或后赋值
^= 按位异或后赋值

流程控制

条件判断(if)

构建循环(for)

键值循环(for range)

分支选择(switch)

goto

break

continue