Go语言学习笔记(二)
一、字符
1、概述
- 字符型存放单个字母或单个文字
- GO语言不支持字符类型,在GO语言中所有字符值都转换为对应的编码表中int32值
- GO语言默认使用UTF8编码
2、编码发展历史
- 最开始使用8个可开合晶体管表示世间万物,这就是字节的由来,后来生产出可以控制字节的机器,出现了计算机
- 把字节中32以下情况称为控制码,后再控制码基础上添加空格、标点符号、数字、大小写字母等直到127,最终形成了ASNI的ASCII码,这是已经较好的支持英文了
- 随着计算机在全球的应用,在原ASCII基础上添加了新的字母、符号、横线竖线等直到255号,从128到255被称为扩展字符集,但是此时计算机还是在支持英文
- 等中国开始使用计算机,为了支持中文,保留了前127号,这些称为半角,把后面的内容以两个字节拼接形成中文汉字和表单符号,这后半部分就是全角,其中汉字6763个满足中文大部分情况的要求称为GB2312
- 随着计算机在中国的普及,使用GB2312时有的汉字无法打出,又在GB2312基础上添加了近20000个汉字(包含繁体和符号等)形成GBK,后来为支持少数民族又在GBK基础上退出了GB18080
- 全球中每个国家都有自己的一套编码,ISO国际为了统一标准,重新定义了一套编码,希望包含全球所有的文字和符号,俗称Unicode
- 随着互联网的快速发展,为缓解Unicode网络传输中流量浪费问题,出现了UTF编码,有UTF-8(8位传输)和UTF-16(16位传输)两种,其中UTF-8使用最多,为变长编码方式,中文占3个字节
二、转义字符
1、转义字符介绍
-
在GO语言中可以使用%+特定字母形成转义字符,这个表示特定含义的组合成为转义字符
-
在GO语言中又称为verb
-
转义字符在GO语言中以下两种情况使用频率较高
fmt.Print("verb",内容)//输出
fmt.Scanf("verb",接受变量)//输入
2、进制描述
- 进制数在编程中经常遇见,进制数分为二进制、八进制、十进制、十六进制,其中十进制就是平常我们接触最多的
- X进制都满足:
- 满X进一位
- 每位最大为X-1
- 第N位代表X的(n-1)次方
- 其中十六进制中a=10,b=11,c=12,d=13,e=14,f=15
3、常用转义字符汇总
Verb | 含义 |
---|---|
%d | 十进制整数 |
%x、%X | 大小写方式显示十六进制整数 |
%o | 八进制整数 |
%b | 二进制整数 |
%f、%g、%e | 浮点数 |
%t | 布尔值 |
%c | 字符 |
%s | 字符串 |
%q | 带双引号字符串 |
%v | 内置格式内容 |
%T | 类型 |
%p | 内存地址 |
%% | 字符% |
\n | 换行 |
\t | 缩进 |
三、用户输入
1、简介
- 用户输入在平时练习中使用频率较高
- 程序运行时,运行到接受用户输入语句会阻塞,等待用户输入,用户输入后,把内容赋值给对应的变量后,程序继续运行
- 在GO语言中有多重接受用户输入的方式,其中使用fmt包的Scan函数使用最简单
2、接收用户输入的几种方式
-
使用Scanln(&变量名,&变量名)的方式接收
- 输入的内容必须都在同一行
- 每个内容之间使用空格分隔
- 回车换行后表示停止输入
- 如果希望接收3个值,而在控制台只输入2个值,回车后也停止接收
- 如果希望接收2个值,而在控制台输入3个,回车后只能接收两个值
package main
import "fmt"
func main() {
var name, age string
fmt.Print("请输入用户姓名和年龄:")
fmt.Scanln(&name, &age)
fmt.Println("接收到内容为:", name, age)
}
-
也可以使用fmt.Scanf(verb,&变量)按照特定的格式进行输入
- 下面例子演示的每次换行输入一个内容
package main
import "fmt"
func main() {
var a, b string
fmt.Println("请输入姓名和年龄:")
fmt.Scanf("%s\n%s", &a, &b)
fmt.Printf("%s\n%s", a, b)
}
- 需要注意,如果同行输入两个字符串,中间使用空格,否则编译器无法对输入内容进行拆分
四、输出
1、打印输出
- 在程序中输出使用频率很高,使用输出语句可以再程序执行过程中把一些结果输出到控制台,程序员通过控制台中输出结果判断是否符合预期
- 在GO语言中有多重输出方式,不同的输出适用场景不同,归纳起来三类,每类又分为三种(原内容、原内容+ln、原内容+f)
- PrintXX()
- FprintXX()
- SprintXX()
2、FprintXX()
- FprintXX在Go Web中使用比较多,把内容写到响应中
- 以Fprintln()举例,源码如下:
// Fprintln formats using the default formats for its operands and writes to w.
// Spaces are always added between operands and a newline is appended.
// It returns the number of bytes written and any write error encountered.
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
p := newPrinter()
p.doPrintln(a)
n, err = w.Write(p.buf)
p.free()
return
}
-
函数参数中第一个参数是输出流,后面参数是内容,表示把内容写入到输出流中
-
第一个返回值表示输出内容长度(字节数),第二个返回值表示错误,如果没有错误取nil
- Fprintln()输出后会添加换行符,所以长度比内容多1个
- Fprintln()源码中p.doPrintln(a)的源码
// doPrintln is like doPrint but always adds a space between arguments
// and a newline after the last argument.
func (p *pp) doPrintln(a []interface{}) {
for argNum, arg := range a {
if argNum > 0 {
p.buf.writeByte(' ')
}
p.printArg(arg, 'v')
}
p.buf.writeByte('\n')
}
-
FprintXX()支持下面三种方式
- os.Stdout表示控制台输出流
func main() {
fmt.Fprint(os.Stdout, "内容1")//向流中写入内容
fmt.Fprintln(os.Stdout, "内容2")//向流中写入内容后额外写入换行符
fmt.Fprintf(os.Stdout, "%s", "内容3")//根据verb格式向流中写入内容
}
3、PrintXX
- PrintXX支持以下三种方式
func main(){
fmt.Println("内容1")//输出内容后换行
fmt.Print("内容2")//输出内容后不换行
fmt.Printf("verb","内容")//根据verb输出指定格式内容
}
- 以Println()举例,源码如下
// Println formats using the default formats for its operands and writes to standard output.
// Spaces are always added between operands and a newline is appended.
// It returns the number of bytes written and any write error encountered.
func Println(a ...interface{}) (n int, err error) {
return Fprintln(os.Stdout, a...)
}
- 可以看出Println()底层实际是Fprintln(),返回值依然是内容长度和错误信息
4、SPrintXX
- 以SPrintln() 为例,和Println()主要的区别是:
- Sprintln()把形式结果以字符串返回,并没有打印到控制台
- Println()把结果打印到控制台,返回内容长度和错误
- 所以严格意义角度讲SprintXX不是打印输出,而更像字符串转换
- 源码如下
// Sprint formats using the default formats for its operands and returns the resulting string.
// Spaces are added between operands when neither is a string.
func Sprint(a ...interface{}) string {
p := newPrinter()
p.doPrint(a)
s := string(p.buf)
p.free()
return s
}
- 也有三种方式
fmt.Sprint("内容1", "内容2")
fmt.Sprintf()
fmt.Sprintln("1", "2")
五、变量声明和赋值
1、静态语言和动态语言
- 静态类型语言和强类型语言是同一个意思,表示在编译器就确定了类型,而且类型是不可以改变的
- 动态类型语言和弱类型语言是同一个意思,表示在运行过程中才能确定且内容是什么类型变量类型跟随变化
2、GO语言变量简介
- go语言和其他语言一样都有基本存储容器,可以存储一个或多个值在程序中,方便程序中多次使用容器中内容,这个容器称为变量
- GO语言虽然是静态类型语言,但是支持动态类型语言语法,因为GO语言希望程序员少声明变量,增加GC效率
3、变量命名规则
- 以字母或下划线开头(GO语言多不以_开头)
- 后面可以是任意数量的字符、数字和下划线
- 区分大小写
- 不能是关键字(关键字具备特定含义),下面是GO语言的关键字
关键字如下 | ||||
---|---|---|---|---|
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语言的保留字
保留字如下 | ||||
---|---|---|---|---|
true | false | iota | nil | int |
int8 | int16 | int32 | int64 | unit |
unit8 | unit16 | unit32 | unitptr | float32 |
float64 | complex128 | complex64 | bool | byte |
rune | string | error | make | len |
cap | new | append | copy | close |
deletecomplex | real | image | panic | recover |
- 在同一范围内不允许出现同名变量
- GO语言要求变量声明后至少使用一次
4、单个变量声明及赋值
- 先声明后赋值(声明后开辟内存,不同类型变量都有不同初始值)
//语法
//1.声明
var 变量名 类型
//2.赋值
变量名=值
- 声明并赋值(此方式不建议)
//语法
var 变量名 类型 = 值
//实例
var smallming string = "英文名"
- 声明并赋值(省略类型,变量类型取决于值的类型)
//语法
var 变量名 = 值
- 短变量(只能在函数内使用)
//语法
变量名 := 值
5、声明多个变量
- 先声明后赋值
func main(){
var a,b,c int
a,b,c = 1,2,3
fmt.Println(a,b,c)
}
- 声明时赋值
func main(){
var a,b,c,d = 1,2,3,false
fmt.Println(a,b,c,d)
}
- 声明并赋值,推荐方式
func main(){
var (
a = 1
b = true
c = "测试"
)
fmt.Println(a,b,c)
}
- 使用短变量给多个变量赋值时,必须要保证至少有两个变量没有声明的
func main(){
var (
a = 1
b = true
c = "测试"
)
b,c,d := false, "smallming", 3
fmt.Println(a,b,c,d)
}
六、整型
1、概述
-
在GO语言中可以进行数据运算的类型分为整型和浮点型
-
所有的整数数字存储到整型中就可以进行数学运算
- 整型和整型运算的结果还是整型(5/2=2)
- 都是整型,但是int8 和int16之间不可以进行运算,必须进行类型转换
-
整型分为有符合整型和无符号整型
- 有符号整型有正数和负数,其二进制最高位表示符号,0为正数1为负数,int和intx为有符号整型
-
无符号整型只能取大于等于0的整数,其二进制最高位表示真实数字,unit和unitx为无符号整型
-
整型取值范围和作用
- 有符号整数统一公式为:-2的n-1次幂到2的n-1次幂减1
-
无符号整数统一公式为
类型 | 取值范围 |
---|---|
int8 | [-128,127] |
int16 | [-32768,32767] |
int32 | [-2147483648,2147483647],GO语言没有字符类型,所有字符都使用int32 |
int64 | [-92233722036854775808,9223372036854775807] |
int | 受限于计算机系统,系统是多少位,int为多少位 |
unit8 | [0,255] |
unit16 | [0,65535] |
unit32 | [0,4294967295] |
unit64 | [0,18446744073709551615] |
uint | 受限于计算机系统,系统是多少位,uint为多少位 |
rune | 与int32类似,常用在获取值的Unicode码 |
byte | 与uint8类似,强调值为原始数据,一个字节占用8个二进制 |
uintptr | 大小不确定,类似取决于底层编程 |
2、类型转换
- GO语言是静态类型语言,并且不具备低精度向高精度自动转换功能,所以不同类型变量之间相互赋值需要进行类型转换
package main
import "fmt"
func main() {
//声明3个类型变量
var a int = 1
var b int32 = 2
var c int64 = 3
fmt.Println(a, b, c)
//把int32转换为int64
a = int(b)
fmt.Println(a, b)
a = 1
//把int64转换为int32
b = int32(c)
fmt.Println(b, c)
b = 2
//把int转换为int64
c = int64(a)
fmt.Println(a, c)
c = 3
}
3、不同进制整数
- 支持八进制、十进制、十六进制数字创建整型,最后由系统转换为十进制
- 不支持二进制值
package main
import "fmt"
func main() {
//默认表示十进制
d := 17
//0开头表示八进制
o := 021
//0x开头表示十六进制
x := 0x11
//e2表示10的2次方
e := 11e2
//输出
fmt.Println(d, o, x, e)
//把变量d中内容转为二进制
b := fmt.Sprintf("%b", d)
fmt.Println(b)
}