第2章 Go语言编程基础

不打扰是莪最后的温柔 提交于 2019-12-18 21:49:24

第2章 Go语言编程基础

2.1 数据类型

2.1.1 基础数据类型

Go语言的数据类型可以用于参数和变量声明,可以分为如下五类:

  • 布尔类型:只可以是常量true或者false。
  • 数字类型:整型int和浮点型float32,float64。
  • 字符串类型:字符串类型是一串固定长度的字符连接起来的字符序列。
  • 复合(派生)类型:包括指针类型(pointer)、数组类型(array)、结构类型(struct)、通道类型(channel)、函数类型(function)、切片类型(slice)、接口类型(interface)和字典类型(map)。
  • 错误类型(error):error类型是Go语言预定义类型。

2.1.2 复合数据类型

Go语言中含有多种复合数据类型,将会在下面的章节中逐个进行讲解。

2.2 变量

2.2.1 变量以及声明

Go语言中由四类标记:标识符(identifiers)、关键字(keywords)、运算符(operators)标点符号(punctuation)以及字面量(literals)。
Go语言的变量标识符由字母、数字、下划线组成,其中首字符不能为数字,变量区分大小写。

变量声明形式有三种:
1)单独声明

	var year int

2)联合声明

	var (
		year int
		month int
		day int
		hour, minute, second int
	)

3)推断式声明

	year, month, day := 2020, 1, 1 //year,month,day未加声明,但会被推断为int类型

2.2.2 零值(nil)

当一个变量被var声明之后,如果没有对其明确指定初始值,Go语言会自动化其值为一个对应的零值。

类型 零值
integer 0
float 0.0
bool false
string 空字符串 “”
pointer interface, error, function, map, slice, channel nil

2.3 常量

2.3.1 常量定义

常量使用const关键字定义,用于存储不变的数字,不可以被重新赋予任何值。
常量只可以是布尔型、数字型和字符串三种类型,定义形式如下:

	const identifier [type] = value

例如:

	const a string = "abc"
	const b = 123
	cosnt c = true

2.3.2 iota

iota比较特殊,可以认为是一个能被编译器修改值得常量,特性如下:

  • 每一个const出现时,被赋值为0
  • iota的值,随行数增长,每次加1
    基于上述特性,iota常被用于作枚举值:
	const (
		// const 定义时,自动集成上一行的值
		a1 = iota // iota = 0, a1 = 0 = iota
		b1        // iota = 1, b1 = 1 = iota
		c1        // iota = 2, c1 = 2 = iota
	)
	const (
		// 遇到const时iota自动赋值为0,且随行数增加自动加1
		a2 = iota // iota = 0, a2 = 0 = iota
		b2 = 8    // iota = 1, b2 = 8
		c2        // iota = 2, c2 = 8
		d2 = iota // iota = 3, d2 = 3 = iota
	)
	const (
		// const 定义时,自动集成上一行的值
		a3, b3 = iota, iota + 1 // iota = 0, a3 = 0, b3 = 1
		c3, d3 =                // iota = 1, c3 = 1, d3 = 2
	)

2.3.3 字面量

在Go语言中,字面量是指由字母、数字等构成的字符串或数值,它只能作为右值出现。
由下面几种字面量

  1. 整数字面量(Iiterals)
	42              //十进制
	0600		    //八进制
	0xBadFace		//十六进制	
	0XBadFace		//十六进制
  1. 浮点数字面量(Floating-point literals)
	7.
	7.2
	.2
	7.2e+1
	7.2e1
	7.2E+1
	7.2E1   //e+1, e1, E+1, E1 都代表前面数字×10
  1. 虚数字面量(Imaginary literals)
	7i
	.2i
	7.2i
  1. Rune字面量(Rune Iiterals)
    Rune字面量是标识符Unicode代码点的整数值。Rune字面量表示用单引号括起来的一个或多个字符,如’x’或’\n’。在单引号内,除了换行符和未转义的单引号外,任何字符都可以出现。
    特别的,几种反斜杠转义允许将任意值编码为ASCII文本:
    1)\x后跟恰好两个十六进制数字;
    2)\u后跟恰好四个十六进制数字;
    3)\U后跟恰好八个十六进制数字;
    4)\后跟恰好三个八进制数字。
  2. 字符串字面量(String literals)
    字符串字面变量表示通过连接字符序列获得字符串常量。有两种形式:原始字符串字面量和解释字符串字面量。
    原始字符串字面量是反引号之间的字符序列。
    解释的字符串字面量是双引号直接的字符序列

2.4 运算符

2.4.1 内置运算符

  1. Go语言的算术运算符
运算符 含义
+ 相加
- 相减
* 相乘
/ 相除
% 求余
++ 自增
自减
  1. Go语言的关系运算符
运算符 含义
== 相等
!= 不等
> 大于
< 小于
>= 大于等于
<= 小于等于
  1. Go语言的逻辑运算符
运算符 含义
&& 逻辑与
|| 逻辑或
! 逻辑非
  1. Go语言的位运算符
运算符 含义
& 按位与
| 按位或
^ 按位异或
<< 左移
>> 右移
  1. Go语言的赋值运算符
运算符 含义
= 简单赋值
+= 相加后赋值
-= 相减后赋值
*= 相乘后赋值
/= 相除后赋值
%= 求余后赋值
<<= 左移后赋值
>>= 右移后赋值
&= 按位与后赋值
^= 按位异或后赋值
= 按位或后赋值
  1. Go语言的其他运算符
运算符 含义 效果
& 返回变量存储地址 &a 将给出变量的实际地址
* 指针变量 *a 是一个指针变量

2.4.2 运算符优先级

一元运算符具有最高优先级。
二元运算符具有五个优先级,优先级高者先运算:

优先级 运算符
5 * / % << >> & &^
4 + -
3 == != < <= > >=
2 &&
1 ||

2.4.3 几个特殊运算符

  1. &^ 位清符
    将制定位置上的值设为0,x&^y = x&(^y)
  2. ^ 异或(XOR)
    ^作为一元运算符出现时,为按位取反的意思。

2.5 字符串

2.5.1 字符串介绍

Go语言中可以使用反引号或长双引号来定义字符串。

  • 反引号:字符串使用反引号括起来,其中的相关转义字符不会被替换。
  • 双引号:字符串使用双引号括起来,其中的相关转义字符会被替换。

Go语言中的string类型是一种值类型,存储的字符串是不可改变的,如果要修改string的内容,需要将string转换为[]byte或[]rune,并且修改后的string内容是重新生成的。

	type byte = uint8
	type rune = int32

string的零值是长度为零的字符串,即空字符串""。
一般的比较符,通过在内存中按字节比较来实现字符串的对比。
可以通过函数len()获取字符串所占的字节长度。
可以通过[]来索引字符串的字节,索引从0开始:

  • 字符串str的第一个字节: str[0]
  • 第i个字节:str[i-1]
  • 最后一个字节str[len(str) - 1]

Go语言默认使用UTF-8编码,对Unicode的支持也非常好。但是len( )获取的是UTF-8编码的长度,而不是直接获取字符数量。

2.5.2 字符串拼接

  1. 直接使用运算符
  str := "abc" + "def"
  1. mt.Sprintf()
  str = fmt.Sprintf("%d%s", 123, "abc")
  1. strings.join()
  str = strings.Join([]string{"abc","def"}, "123")
  1. bytes.Buffer
	var buffer bytes.Buffer
	buffer.
  1. strings.Builder
	var buf strings.Builder
	buf.WriteString("abc")
	buf.WriteString("def")
	str := buf.String()

2.5.3 字符串处理

标准库中有四个包对字符串进行处理非常重要:bytes, strings, strconv 和 unicode

  • strings包提供了许多字符串查询、替换、比较、截断、拆分和合并等功能。
  • bytes包提供了很多类似的功能函数,但是针对和字符串有相同结构的 [ ]byte类型
  • strconv包提布尔型、整数型、浮点数和对应字符串的转换,还提供了双引号转义的相关函数。、
  • unicode包提供了IsDigit,IsLetter,IsUpper和IsLower等类似功能,用于给字符分类。

2.6 流程控制

2.6.1 switch语句

switch语句提供多路执行,将表达式或类型说明符与“switch”内的“case”进行比较,以确定需要执行的分支。

switch有两种形式:表达式型switch和类型型switch。在表达式型switch中,包含与switch表达式的值进行比较的表达式;在类型型switch中,包含与switch表达式的类型进行比较的类型。

Go语言中,switch的每个分支默认带有break,如果需要继续执行可以使用fallthrough强制执行下一条分支的代码,并忽略分之前表达式的结果是否正确。特别的,switch的最后一个分支不可以使用fallthrough。

switch主要有三种形式:

  1. switch后接一个表达式
	switch var1 {
		case val1:
			...
		case val2:
			...
		default:
			...
	}
  1. switch后不接任何东西,相当于switch true
	switch{
		case condition1:
			...
		case condition2:
			...
		default:
			...
	}
  1. switch后接一个初始化语句
	switch initialization{
		case val1:
			...
		case val2:
			...
		default:
			...
	}

特别的,switch后接类型

	switch x.(type){
	    case type1:
	       statement(s);      
  		case type2:
       		statement(s); 
    		/* 你可以定义任意个数的case */
    	default: /* 可选 */
    		statement(s);
    }

2.6.2 select语句

select是Go语言中的一个控制结构,类似于switch语句,每个case必须是一个通信操作,要么是发送要么是接收。
select随机执行一个可运行的case,如果没有case可以运行,它将阻塞,直到case可运行,default是一个默认的字句应该总是可以运行。

select {
    case communication clause  :
       statement(s);      
    case communication clause  :
       statement(s);
    /* 你可以定义任意数量的 case */
    default : /* 可选 */
       statement(s);
}

特别的:

  • 每个case都是一个通信
  • 所有channel表达式都会被求值
  • 所有发送的表达式都会被求值
  • 如果任意某个通信可以进行,他就会执行,其他被忽略
  • 如果多个case都可以运行,select会随机公平地选择出一个执行,其他不会执行。
  • 若没有可执行的case,则默认执行default子句
  • 若没有default子句,select将阻塞,直到某个通信可以进行;Go 不会重新对 channel 或值进行求值。

2.6.3 for语句

for语句是最简单的基于计数器的循环迭代,基本形式为:

	for 初始化语句; 条件语句; 修饰语句{
		......
	}

2.6.4 for-range结构

for range 结构是Go语言特有的一种迭代结构,它在许多情况下都非常有用。它可以迭代任何一个集合,包括数组和字典,同时可以带带对应的索引和值,一般形式为:

	for ix, val := range coll {
		......
	}

2.6.5 if语句

if语句是由布尔表达式紧跟一个或多个语句组成。特别的,布尔表达式不用()。
一般形式为:

	if 布尔表达式{
		......
	} else {
		......
	}

2.6.6 break语句

一个break的作用范围为该语句出现后的最内部结构,他可以用于任何的非顺序语句。
但在switch或select语句中,break语句的作用是跳过整个代码块。

2.6.7 continue语句

关键字continue忽略剩余的循环体而直接进入下一次循环的过程,但是不是无条件的执行下一次循环,执行之前依旧要满足循环条件。

2.6.8 标签

for、switch或select语句都可以配合标签(label)形式的标识符使用,即某一行第一个以冒号结尾的单词。标签的名称是大小写敏感的,为了提高可读性,一般建议全用大写字母。

	ERROR:
		log.Panic("error encountered")

2.6.9 goto语句

goto语句就是调到具有相同函数内响应标签的语句。

	goto ERROR

破坏代码结构的完整性,不鼓励使用。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!