在 Go 编程语言中,数据类型用于声明函数和变量

  • 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存
  • Go 语言按类别有以下几种数据类型:
类型 描述
布尔型 bool 布尔型的值只可以是常量 true 或者 false
一个简单的例子:var b bool = true
数字类型 uintptr 无符号整型,用于存放一个指针
byte 类似 uint8
int 32 或 64 位
rune 类似 int32
uint 32 或 64 位
整型 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)
浮点型 float32
IEEE-754 32位浮点型数
float64
IEEE-754 64位浮点型数
复数 complex64
32 位实数和虚数
complex128
64 位实数和虚数
字符串类型 string 字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本
派生类型
(a) 指针类型(Pointer)
(b) 数组类型
(c) 结构化类型(struct)
(d) Channel 类型
(e) 函数类型
(f) 切片类型
(g) 接口类型(interface)
(h) Map 类型

bool

bool 类型表示一个布尔值,值为 true 或者 false

  1. package main
  2. import (
  3. "fmt"
  4. "unsafe"
  5. )
  6. func main() {
  7. a := true
  8. b := false
  9. fmt.Println("a:", a, "b:", b)
  10. c := a && b
  11. fmt.Println("c:", c)
  12. d := a || b
  13. fmt.Println("d:", d)
  14. fmt.Println("unsafe.Sizeof(d) =", unsafe.Sizeof(d))
  15. }

在上面的程序中,a 赋值为 true,b 赋值为 false。
c 赋值为 a && b。仅当 a 和 b 都为 true 时,操作符 && 才返回 true。因此,在这里 c 为 false。
当 a 或者 b 为 true 时,操作符 || 返回 true。在这里,由于 a 为 true,因此 d 也为 true。我们将得到程序的输出如下

  1. a: true b: false
  2. c: false
  3. d: true
  4. unsafe.Sizeof(d) = 1

⚠️ 为了得到某类型或某变量在特定平台上的准确大小,可以使用 unsafe.Sizeof(type)获取对象或类型的存储字节大小

int

根据不同的底层平台(Underlying Platform),表示 32 或 64 位整型。除非对整型的大小有特定的需求,否则通常应该使用 int 表示整型
大小 在32位系统下是32位,而在64位系统下是64位
范围 在 32 位系统下是 -2147483648~2147483647,而在 64 位系统是 -9223372036854775808~9223372036854775807

  1. package main
  2. import "fmt"
  3. func main() {
  4. var a int = 89
  5. b := 95
  6. fmt.Println("value of a is", a, "and b is", b)
  7. }

在 Printf 方法中,使用 %T 格式说明符(Format Specifier),可以打印出变量的类型。Go 的 unsafe 包提供了一个 Sizeof 函数,该函数接收变量并返回它的字节大小。unsafe 包应该小心使用,因为使用 unsafe 包可能会带来可移植性问题。不过出于本教程的目的,我们是可以使用的。
下面程序会输出变量 a 和 b 的类型和大小。格式说明符 %T 用于打印类型,而 %d 用于打印字节大小。

  1. package main
  2. import (
  3. "fmt"
  4. "unsafe"
  5. )
  6. func main() {
  7. var a int = 89
  8. b := 95
  9. fmt.Println("value of a is", a, "and b is", b)
  10. fmt.Printf("type of a is %T, size of a is %d", a, unsafe.Sizeof(a)) // a 的类型和大小
  11. fmt.Printf("\ntype of b is %T, size of b is %d", b, unsafe.Sizeof(b)) // b 的类型和大小
  12. }

以上代码运行输出:

  1. [Running] go run "/Users/Ken/Desktop/test/main.go"
  2. value of a is 89 and b is 95
  3. type of a is int, size of a is 8
  4. type of b is int, size of b is 8
  5. [Done] exited with code=0 in 0.804 seconds

从上面的输出,我们可以推断出 a 和 b 为 int 类型,且大小都是 64 位(8 字节)。如果在 32 位系统下,a 和 b 会占用 32 位(4 字节)的大小

浮点型

float32:32 位浮点数
float64:64 位浮点数

  1. package main
  2. import ( "fmt"
  3. )
  4. func main() {
  5. var c float32
  6. a, b, c:= 5.67, 8.97, 1.1
  7. fmt.Printf("type of a %T b %T c %T\n", a, b, c)
  8. sum := a + b
  9. diff := a - b
  10. fmt.Println("sum", sum, "diff", diff)
  11. no1, no2 := 56, 89
  12. fmt.Println("sum", no1+no2, "diff", no1-no2)
  13. }

a 和 b 的类型根据赋值推断得出。在这里,a 和 b 的类型为 float64(float64 是浮点数的默认类型)。我们把 a 和 b 的和赋值给变量 sum,把 b 和 a 的差赋值给 diff,接下来打印 sum 和 diff。no1 和 no2 也进行了相同的计算。上述程序将会输出:

  1. [Running] go run "/Users/Ken/Desktop/test/main.go"
  2. type of a float64 b float64 c float32
  3. sum 14.64 diff -3.3000000000000007
  4. sum 145 diff -33
  5. [Done] exited with code=0 in 0.338 seconds

复数类型

complex64 实部和虚部都是 float32 类型的的复数
complex128 实部和虚部都是 float64 类型的的复数

内建函数 complex

用于创建一个包含实部和虚部的复数。complex 函数的定义如下:

  1. func complex(r, i FloatType) ComplexType

该函数的参数分别是实部和虚部,并返回一个复数类型。实部和虚部应该是相同类型,也就是 float32 或 float64

  • 如果实部和虚部都是 float32 类型,则函数会返回一个 complex64 类型的复数
  • 如果实部和虚部都是 float64 类型,则函数会返回一个 complex128 类型的复数

简短语法来创建复数

  1. c := 6 + 7i

下面我们编写一个简单的程序来理解复数:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. c1 := complex(5, 7)
  7. c2 := 8 + 27i
  8. cadd := c1 + c2
  9. fmt.Println("sum:", cadd)
  10. cmul := c1 * c2
  11. fmt.Println("product:", cmul)
  12. }

在上面的程序里,c1 和 c2 是两个复数。c1的实部为 5,虚部为 7。c2 的实部为8,虚部为 27。c1 和 c2 的和赋值给 cadd ,而 c1 和 c2 的乘积赋值给 cmul。该程序将输出:

  1. sum: (13+34i)
  2. product: (-149+191i)
  • 加法法则
    • 复数的加法按照以下规定的法则进行:设c1=a+bi,c2=c+di是任意两个复zhi数
    • 则它们的和是 (a+bi)+(c+di)=(a+c)+(b+d)i
    • 两个复数的和依然是复数,它的实部是原来两个复数实部的和,它的虚部是原来两个虚部的和
  • 减法法则
    • 复数的减法按照以下规定的法则进行:设c1=a+bi,c2=c+di是任意两个复数
    • 则它们的差是 (a+bi)-(c+di)=(a-c)+(b-d)i
    • 两个复数的差依然是复数,它的实部是原来两个复数实部的差,它的虚部是原来两个虚部的差
  • 乘法法则
    • 设c1=a+bi,c2=c+di(a、b、c、d∈R)是任意两个复数
    • 那么它们的积(a+bi)(c+di)=(ac-bd)+(bc+ad)i
    • 其实就是把两个复数相乘,类似两个多项式相乘,展开得: ac+adi+bci+bdi2,因为i2=-1,所以结果是(ac-bd)+(bc+ad)i 。两个复数的积仍然是一个复数
  • 除法法则
    • 复数除法定义:满足(c+di)(x+yi)=(a+bi)的复数x+yi(x,y∈R)叫复数a+bi除以复数c+di的商。
    • 运算方法:可以把除法换算成乘法做,在分子分母同时乘上分母的共轭.。所谓共轭你可以理解为加减号的变换,互为共轭的两个复数相乘是个实常数

image.png

string 类型

在 Golang 中,字符串是字节的集合。如果你现在还不理解这个定义,也没有关系。我们可以暂且认为一个字符串就是由很多字符组成的。我们后面会在一个教程中深入学习字符串。
下面编写一个使用字符串的程序

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. first := "Naveen"
  7. last := "Ramanathan"
  8. name := first +" "+ last
  9. fmt.Println("My name is",name)
  10. }
  11. /* 上面程序中,first 赋值为字符串 “Naveen”
  12. last 赋值为字符串 “Ramanathan”。+ 操作符可以用于拼接字符串
  13. 我们拼接了 first、空格和 last,并将其赋值给 name
  14. 上述程序将打印输出 My name is Naveen Ramanathan */

类型转换

类型转换用于将一种数据类型的变量转换为另外一种类型的变量

Go 语言类型转换基本格式

  1. type_name(expression)

type_name 为类型,expression 为表达式

整型转化为浮点型的示例

以下实例中将整型转化为浮点型,并计算结果,将结果赋值给浮点型变量:

  1. package main
  2. import "fmt"
  3. func main() {
  4. var sum int = 17
  5. var count int = 5
  6. var mean float32
  7. mean = float32(sum)/float32(count)
  8. fmt.Printf("mean 的值为: %.2f\n",mean)
  9. }
  10. /*
  11. 以上实例执行输出结果为:
  12. mean 的值为: 3.40
  13. */

Go 有着非常严格的强类型特征。Go 没有自动类型提升或类型转换。我们通过一个例子说明这意味着什么

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. i := 55 //int
  7. j := 67.8 //float64
  8. sum := i + j //invalid operation: i + j (mismatched types int and float64)
  9. fmt.Println(sum)
  10. }
  11. /* 上面的代码在 C 语言中是完全合法的,然而在 Go 中,却是行不通的。
  12. i 的类型是 int ,而 j 的类型是 float64 ,
  13. 我们正试图把两个不同类型的数相加,Go 不允许这样的操作。
  14. 如果运行程序,你会得到invalid operation: i + j (mismatched types int and float64) */

要修复这个错误,i 和 j 应该是相同的类型。在这里,我们把 j 转换为 int 类型。把 v 转换为 T 类型的语法是 T(v)

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. i := 55 //int
  7. j := 67.8 //float64
  8. sum := i + int(j)
  9. fmt.Println(sum)
  10. }

现在,当你运行上面的程序时,会看见输出 122

赋值的情况也是如此。把一个变量赋值给另一个不同类型的变量,需要显式的类型转换

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. i := 10
  7. var j float64 = float64(i) // 若没有显式转换,该语句会报错
  8. fmt.Println("j", j)
  9. }
  10. /* 在第8行,i 转换为 float64 类型,接下来赋值给 j。
  11. 如果不进行类型转换,当你试图把 i 赋值给 j 时,编译器会抛出错误。 */

GO输出打印的格式

GO语言中的格式说明符

printf() 函数的输出格式(Format Specifier)

类型 格式 描述 示例
General %v 以默认的方式打印变量的值
%T 打印变量的类型
Integer %+d 带符号的整型 fmt.Printf(“%+d”, 255)
+255
%q 打印单引号
%o 不带零的八进制
%#o 带零的八进制
%x 小写的十六进制
%X 大写的十六进制
%#x 带0x的十六进制
%U 打印Unicode字符
%#U 打印带字符的Unicode
%b 打印整型的二进制


Integer width
%d 以十进制形式输出数据
%ld 表示按十进制长整型输出
%5d 表示该整型最大长度是5,下面这段代码 fmt.Printf(“|%5d|”, 1)
fmt.Printf(“|%5d|”, 1234567)

输出结果如下:
| 1|
|1234567|
%-5d 则相反,打印结果会自动左对齐
%05d 会在数字前面补零
Float %f 以浮点型形式输出数据,默认保留小数点后6位; %.3f 最多3位小数来表示
%.6f 表示显示6位小数点
%e 小数点(
科学计数法
)
%.6e 表示6位小数点
%g 用最少的数字来表示
%.3g 最多3位数字来表示

%c 以字符形式输出数据
String %s 正常输出字符串
%q 字符串带双引号,字符串中的引号带转义符
%#q 字符串带反引号,如果字符串内有反引号,就用双引号代替
%o 以八进制形式输出数据
%x 将字符串转换为小写的16进制格式
%X 将字符串转换为大写的16进制格式
/% x 带空格的16进制格式

%s 以字符串形式输出数据
String Width
(以5做例子)
%5s 最小宽度为5
%-5s 最小宽度为5(左对齐)
%.5s 最大宽度为5
%5.7s 最小宽度为5,最大宽度为7
%-5.7s 最小宽度为5,最大宽度为7(左对齐)
%5.3s 如果宽度大于3,则截断
%05s 如果宽度小于5,就会在字符串前面补零
Struct %v 正常打印 {sam {12345 67890}}
%+v 带字段名称 {name:sam phone:{mobile:12345 office:67890}
%#v 用Go的语法打印 比如main.People{name:”sam”, phone:main.Phone{mobile:”12345”, office:”67890”}}
Boolean %t 打印true或false
Pointer %p
带0x的指针
地址形式输出数据

%#p 不带0x的指针
地址形式输出数据

Go 进度条功能实现

pic_001.gif

  1. package main
  2. import(
  3. "fmt"
  4. "time"
  5. )
  6. type Bar struct {
  7. percent int64 //百分比
  8. cur int64 //当前进度位置
  9. total int64 //总进度
  10. rate string //进度条
  11. graph string //显示符号
  12. }
  13. func (bar *Bar) NewOption(start, total int64) {
  14. bar.cur = start
  15. bar.total = total
  16. if bar.graph == "" {
  17. bar.graph = "█"
  18. }
  19. bar.percent = bar.getPercent()
  20. for i := 0; i < int(bar.percent); i += 2 {
  21. bar.rate += bar.graph //初始化进度条位置
  22. }
  23. }
  24. func (bar *Bar) NewOptionWithGraph(start, total int64, graph string) {
  25. bar.graph = graph
  26. bar.NewOption(start, total)
  27. }
  28. func (bar *Bar) getPercent() int64 {
  29. return int64(float32(bar.cur) / float32(bar.total) * 100)
  30. }
  31. func (bar *Bar) Play(cur int64) {
  32. bar.cur = cur
  33. last := bar.percent
  34. bar.percent = bar.getPercent()
  35. if bar.percent != last && bar.percent%2 == 0 {
  36. bar.rate += bar.graph
  37. }
  38. fmt.Printf("\r[%-50s]%3d%% %8d/%d", bar.rate, bar.percent, bar.cur, bar.total)
  39. }
  40. func (bar *Bar) Finish(){
  41. fmt.Println()
  42. }
  43. func main() {
  44. var bar Bar
  45. // bar.NewOption(0, 100)
  46. bar.NewOptionWithGraph(0, 100, "#")
  47. for i:= 0; i<=100; i++{
  48. time.Sleep(100*time.Millisecond)
  49. bar.Play(int64(i))
  50. }
  51. bar.Finish()
  52. }

python语言中的格式说明符

1. 字符串格式代码

符号 说明
%s 字符串
%c 字符
%d 十进制(整数)
%i 整数
%u 无符号整数
%o 八进制整数
%x 十六进制整数
%X 十六进制整数大写
%e 浮点数格式1
%E 浮点数格式2
%f 浮点数格式3
%g 浮点数格式4
%G 浮点数格式5
%% 文字%

2. 常用转义字符

转义符号 描述
\(在尾行时) 续行符
\\ 反斜杠符号
\’ 单引号
\” 双引号
\a 响铃
\b 退格(Backspace)
\e 转义
\000
\n 换行
\v 纵向制表符
\t 横向制表符
\r 回车
\f 换页
\oyy 八进制数yy代表的字符
例如:\o12 代表换行
\xyy 十进制数yy代表的字符
例如:\x0a12 代表换行
\other 其他的字符以普通格式输出