【GO语言卵细胞级别教程】02.GO变量和数据类型

发布时间:2024年01月20日

【GO语言卵细胞级别教程】02.GO变量和数据类型

声明:
(1) GO版本:go version go1.21.5 windows/amd64
(2) 开发工具:vscode
(3) 微信公众号:给点知识
如果版本不一样再环境变量的配置上多少有点问题。1.11 GO版本之前使用GOPATH 之后可以使用go.mod 要不然导入模块包那块会有问题。

1.变量

#数据类型-变量 #Go变量

1.0 变量介绍

变量相当于内存中一个数据存储空间的表示,一般需要有变量的名称和类型
比如:var name int =18

1.1 变量命名规范

  1. 使用字母 数字 字母 下划线 中文(但不建议使用中文)
package main

import "fmt"

func main() {
	var 名字 string = "张三"
	var 年龄 int = 18
	var 身高 float32 = 180.9
	fmt.Println(名字, 年龄, 身高)
}

  1. 不能以数字开头, 不能使用关键词作为变量,比如int float32 string等,
    其实关键词你非要使用也可以使用,但是会有一定的问题。
    比如:
    定义了:var float32 int = 10
    这个时候关键词float32 变成了一个整数,如果你再使用float32定义变量的时候就会报错,因为这个时候它是整数
    var score float32 = 19,这个就会报错了。如下图:
    在这里插入图片描述

  2. 区分大小写,可以以字母、下划线开头

package main
import "fmt"
func main() {
    var _名字 string = "张三"
    var z年龄 int = 18
    var Z年龄 int = 20
    var 身高 float32 = 180.9
    fmt.Println(_名字, Z年龄, z年龄, 身高)
}
  1. 下划线作用
    (1)与字母、数字组合成变量
    (2)单独使用的时候可以作为占位符,不能作为标识符
    (3)作为忽略符号使用:导入包的时候,为了防止编译不过去某个没有使用的包,可以加入下划线作为忽略
package main
import "fmt"
import _ "strconv"
func main() {
    var _名字 string = "张三"
    var float32 int = 18
    fmt.Println(float32, _名字)
}
  1. 包名规则

    1. 包名尽量保持package的名字和目录保持一致,
    2. 程序的入口包必须是main包在这里插入图片描述
    3. 尽量采取有意义的包名,简短,有意义
    4. 不要和标准库有冲突,比如不能定义一个:package fmt
  2. 变量使用字母大小写实现,使用小驼峰实现。

    1. 注意如果是让其他模块可以使用的那就需要首字母大写,也就是大驼峰,否则就是小驼峰即可
    2. 大驼峰GetName() 小驼峰写法 getName
    3. 首字母大写代表可以被访问其他模块可以访问,相当于公共变量,首字母小写表示私有变量,如下图
创建目录结构
D:.
└─demo01
   ├─main
   |---main.go
   └─utils
   |---mymath.go
--go.mod // 不用自己创建,接着往下看
1. `go.mod` 文件是一个文本文件,位于项目的根目录下。它记录了项目所依赖的模块及其版本信息,并定义了模块的路径。
2. 创建好文件以及目录后填充内容
3. main.go
package main
import (
   f"fmt"
   "gdzs/demo01/utils"
)
func main(){
   f.Println("---------")
   f.Println(utils.PackageName)
}
4. mymath.go
package utils

var Num int = 1
var PackageName string = "这里是工具模块的PackageName变量"
var name string = "名字"
5. cd demo01
6. go mod init gdzs 就会生成go.mod 文件
7. 这个时候执行go demo01/main/main.go即可看到结果

注意,这里因为Code Runner 这个插件执行的目录是在vscode 添加的根目录下执行的,上图就是再01.test目录下执行的。注意如果打开的是上一级目录就会报错,例如

PS D:\07.go\01.test> cd ..
PS D:\07.go> go run .\demo01\main\main.go
CreateFile .\demo01\main\main.go: The system cannot find the path specified.

所以解决办法就是需要保证demo01和go.mod再同一个目录,且上级目录就是vscode打开的根目录,如图所示
在这里插入图片描述

1.2 变量声明

#GO变量声明

1.2.1 单个变量声明

  1. 声明的格式
1. 第一种:直接赋值: var age int = 12
2. 第二种:只复制类型赋值后赋值变量: var num int 
3. 第三种:没有写类型,通过值进行自动判断 var name="张三"4. 第四种:省略var 使用 := 代替
  1. 实战
package main
import "fmt"
func main() {
    // 第一种变量
    var age int = 18
    fmt.Println("age is ", age)
    // 第二种变量定义方式 不赋值 使用默认值
    var num int
    fmt.Println("num is ", num)
    // 第三种变量如果没有写变量的类型,那么根据=后面的值进行判断类型
    var name = "张三"
    println("name is:", name)
    // 第四种,省略var 使用 【:=】代替
    name2 := "里斯"
    println("name2 is:", name2)
}

1.2.2 多个变量声明

#Go多个变量声明

  1. 格式
1. 格式1var age, name = 18, "张三"
2. 格式2var (
   n1=18
   n2="name"
   n3 int = 100
)
  1. 实践
package main
import "fmt"
func main() {
    var n1, n2, n3 = 19, "java", 7
    println(n1, n2, n3)
    println("------")
    // 定义多个变量,并且赋值多个
    var (
        m1 int    = 10
        m2 string = "|王五|"
        m3        = 100
    )
    println(m1, m2, m3)
    println("------")
}

1.2.3 全局变量与局部变量

#GO全局与局部变量

  1. 全局变量:
    (1)就是定义在函数体外部的变量,可以在程序的任意地方使用
    (2)作用域跨域整个程序
    (3)全局变量可以在不同函数中共享和访问
    (4)不能使用 := 声明变量
1. 创建文件main.go
package main
import "fmt"
var globalVariable int = 10
func main() {
   fmt.Println(globalVariable) // 输出:10
}

注意全局变量不能使用 先声明后赋值的方式
在这里插入图片描述

注意全局变量不能使用 := 定义赋值变量
在这里插入图片描述

  1. 局部变量
    (1)局部变量是在函数内部声明的变量,只能在其所在的函数内部访问。
    (2)局部变量的作用域仅限于声明它的函数内部。
    (3)每当函数被调用时,都会为局部变量分配内存空间,函数执行完毕后,该内存空间被释放。
    (4)局部变量可以使用那四种方式进行定义变量 1.2.1 单个变量声明 可以使用:= 声明变量

1.2.4 综合实践

  1. 请听题:实现使用四种定义变量的方式
    (1)使用全局变量定义一个学生的信息:姓名、年龄、身高、备注
    (2)使用局部变量定义一个学生的信息:姓名、年龄、身高、备注
    (3)打印出对应的信息,格式不限
package main
import "fmt"
/*
 实现定义一个学生的信息
 并打印出来
*/
var (
    name2       = "张三"
    age2    int = 12
    notes2      = "中国国人"
    height2     = 178
)
func main() {
    // 第一种定义方式
    var name = "jark"
    // 第二种第一方法是
    var age int = 10
    // 第三种就是定义好后在赋值
    var notes string
    // 第四种 使用:=代替 var
    height := 180
    notes = "学生的基本信息"
    message := fmt.Sprintf("name:%s"+
        "\nage:%d"+
        "\nheight:%d"+
        "\nnotes:%s",
        name, age, height, notes)
    fmt.Println(message)
    fmt.Println("---------------")
    fmt.Println("使用全局变量")
    message2 := fmt.Sprintf("name2:%s"+
        "\nage2:%d"+
        "\nheight2:%d"+
        "\nnotes2:%s",
        name2, age2, height2, notes2)
    fmt.Println(message2)
}

2.数据类型

2.1.类型简介

2.2.整数类型

2.2.1 有符号的整数类型

  1. 简介
    (1)int8 一个字节,8位 表数范围:-27~27-1 也即是(-128~127)
    (2)int16 两个字节 16位 表述范围就是 -215~215-1 (-32768~-32767)
    在这里插入图片描述

为什么这个int8 范围是-128到127呢,这里只讲一个,剩下的都是类似的

1.因为这个int8 有一个字节,一般一个字节表示为8位(一些特定的嵌入式系统或硬件平台可能使用非标准的字节大小,如 6 位、7 位或 9 位。这些非标准字节大小可能出于特定的设计需求或历史原因。)
2.因为是8个比特位,且一般第一位为符号位所以
正数范围就是(二进制表示):00000000-01111111 也就是0-127 
负数范围就是(二进制表示):10000000-11111111 可以看到 是负数的0-127 
那么问题来了,哪来的-128呢?
因为0 这个数没有正负之分,所以就把10000000 这个位用于表示-128 所以这里的范围就是-128-127
  1. 实战测试
    (1)把以上的四种类型都定义出来,使用int8 int16 int32 int64 分别定义年龄,并打印出对应值以及类型比如
    var age1 int8 = 18
    age1=18,type=int8
    提示:这里使用了fmt.Printf("%T“,age1)用于打印类型
package main
import "fmt"
func main(){
    var age1 int8 = 23
    var age2 int16 = 28
    var age3 int32 = 18
    var age4 int64 = 21
    fmt.Printf("age1=%d,type=%T", age1, age1)
    fmt.Println()
    fmt.Printf("age2=%d,type=%T", age2, age2)
    fmt.Println()
    fmt.Printf("age3=%d,type=%T", age3, age3)
    fmt.Println()
    fmt.Printf("age4=%d,type=%T", age4, age4)
    
}

// 输出结果
age1=23,type=int8
age2=28,type=int16
age3=18,type=int32
age4=21,type=int64

有意思的是:如果你输出的整数超出范围,那么编译器会自动标红,编译的时候无法通过,这也是go语法的严谨性。

2.2.2 无符号的整数类型

  1. 简介:有符号的数据类型前面加个u就是无符号的了
    (1)类型主要有以下几个,记住就行了,记不住也没事
    uint8 1字节 0~255
    uint16 2字节 0~2^16-1
    uint32 4字节 0~2^32-1
    uint64 8字节 0~2^63-1
    这里举个例子,为什么范围是这么多,举例使用uint8
    uint8:0~255 因为没有符号,所以八个比特位就是从全0到全1
    0000 0000 = 0
    1111 1111 = 255 = 2^8-1
    因为 1111 1111 + 1 = 10000 0000 = 2^8 所以这里 1111 1111= 2^8-1了
  2. 实战测试
    题目:编写一个程序,声明两个无符号整数,两两类型必须相同,打印出来他们的和分别为以下结果:
    500; 1,000; 200,000; 9,000,000,000
package main
/*
求两个数的和,和的结果分别为
500; 1,000; 200,000;  9,000,000,000
*/
import "fmt"
func main() {
    var num1 uint8 = 249
    var num2 uint8 = 251
    fmt.Printf("%d+%d=", num1, num2)
    // 以下赋值导致数据溢出
    // var sum1 = num1 + num2
    sum1 := uint16(num1) + uint16(num2)
    fmt.Printf("%d; sum1类型是:%T\n", sum1, sum1)
    
	// 同理1000  也是这么计算的
    var num3 uint16 = 500
    var num4 uint16 = 500
    fmt.Printf("%d+%d=", num3, num4)
    // 以下赋值导致数据溢出
    // var sum1 = num1 + num2
    sum2 := num3 + num4
    fmt.Printf("%d; sum2类型是:%T\n", sum2, sum2)
    // 剩下的两个自己动手实现了

}

2.2.3 其他整数类型

  1. 简介
    int 有符号 存储空间跟着系统不同而不同如果系统是32 那就是32 范围系统位数不同而不同
    系统是64,那么就是64
    uint 无符号 存储空间随着系统不同而不同

rune 有符号 等价于int32 这个类型是GO独特的,其实它就是int32的别名,翻译中文为符文的意思,
Go语言引入了rune类型,主要是为了处理Unicode字符。Unicode是一种字符集,包含了几乎所有世界上使用的字符,包括不同语言的字母、符号、表情符号等。用了别名rune带有符文符号的意思,所以这里用了rune 其实大家记住是int32就行了。
至于为什么不用uint32 主要怕后面unicode出现负数情况。但是现在没出现,为的是将来,将来懂么!
至于unicode字符集是什么:Unicode字符集旨在覆盖全世界范围内的语言和符号

byte 无 等价于uint8
在这里插入图片描述

  1. 实战测试
package main
/*
其它类型
int uint rune byte 
*/
import "fmt"
func main() {
    var num1 int = 100000000
    var num2 rune = 72
    var num3 uint = 111111111111
    var num4 byte = 121
    fmt.Printf("num1=%d,num2=%d,num3=%d"+
        "num4=%d,rune2=%c",
        num1, num2,
        num3, num4, num4,
    )
}
// 输出结果
num1=100000000,num2=72,num3=111111111111num4=121,rune2=y
其中%c表示输出字符

2.2.4 总结

  1. 在Go语言中,我们选择数据类型的时候尽量选用适当的,比如我们用年龄的话,首先分析年龄这个一般就是0-150 所以这里我们如果使用0-255 的uint8 或者byte 都是可以的
  2. 一般在使用中,整数类型,我们使用int足以
  3. 整数类型分类:Go语言提供了多个整数类型,包括有符号整数类型和无符号整数类型。有符号整数类型包括int8、int16、int32和int64,无符号整数类型包括uint8、uint16、uint32和uint64。
  4. 默认整数类型:在没有指定整数类型的情况下,整数常量的默认类型是int。这意味着如果你写下一个整数常量,如42,它将被认为是int类型。
  5. rune类型:rune是Go语言中的特殊整数类型,用于表示Unicode码点。它是int32的别名,用于处理Unicode字符。
  6. byte类型:byte也是Go语言中的特殊整数类型,它是uint8的别名。byte类型通常用于表示ASCII字符。
  7. 类型转换:当需要将一个整数类型转换为另一个整数类型时,可以使用类型转换操作符进行转换。需要注意的是,类型转换可能导致数据溢出或精度丢失。
  8. 溢出和溢出检查:Go语言的整数类型在发生溢出时会进行截断,即丢弃最高位的位值。如果需要进行溢出检查,可以使用math包中的相应函数来检查整数的范围。
  9. 如果想打印出变量的类型使用%T 如果想查看数值对应的unicode符号则使用%c
  10. 查看字符串占用的字节使用unsafe.sizeof(num1)打印出字节,rune类型的就会打印出4,注意要导入包import “unsafe”
  11. 在Go语言中,整数类型的大小取决于具体的类型。以下是Go语言中整数类型的最大值:
  • int8:最大值为127
  • int16:最大值为32767
  • int32:最大值为2147483647
  • int64:最大值为9223372036854775807
  • uint8(即byte):最大值为255
  • uint16:最大值为65535
  • uint32:最大值为4294967295
  • uint64:最大值为18446744073709551615
    需要注意的是,以上是基于标准的整数类型的最大值。如果你需要更大范围的整数,可以使用math/big包中的big.Int类型,它可以表示任意大小的整数。
举例使用big创建更大的数
import “big"
var num7 = new(big.Int)
num7.SetString("15646545646545456456454546545465445623", 10)
fmt.Print(num7)
//使用自大的答应方法
println(num7.String())

2.3 浮点类型

#浮点类型 #Go变量浮点类型

2.3.1 类型简介

  1. 浮点类型介绍
    耳熟能详的浮点类型就是小数1.99 3.14 等这种
  2. 浮点类型的种类
    float32 4字节 有符号
    float64 8字节 有符号
    浮点型的底层存储:符号位+指数位+尾数位
  3. 代码表示
    (1)赋值整数 var num1 float32 = 3.14
    (2)赋值负数 var num2 float32 = -3.13
    (3)科学计数法表示var num3 float32 = 314E-2 表示314x10^-2
    (4)科学计数法表示var num4 float32 = 314E+2 表示314x10^+2
    (5)科学计数法E大小写都可以
    (6)精度计算
    var num5 float32 = 1223.000000000036
    var num6 float64 = 1223.000000000036
    打印结果float32 精度低
package main
/*
浮点类型
*/
import "fmt"
func main() {
    var f1 float32 = 123.0000000016
    var f2 float64 = 123.0000000016
    println(f1, f2, " 结果1")
    fmt.Println(f1, f2, " 结果2")
    fmt.Print(f1, f2, " 结果3")
}
// 打印结果
+1.230000e+002 +1.230000e+002  结果1
123 123.0000000016  结果2
123 123.0000000016 结果3

科学计数法
注意:如果没有指定浮点类型,那么默认就是float64

package main
/*
浮点数科学计数法
*/
import "fmt"

func main() {
	// 定义浮点类型
	var k1 float32 = 3.14
	// 定义科学计数法10-2次方 大写E
	var k2 float32 = 314e-2
	// 定义科学计数法10-2次方 小写e
	var k3 float32 = 3141592654e-2
	// 定义科学计数法102次方 大写E
	var k4 float64 = 0.03141592654e+2
	// 定义科学计数法10-2次方 小写e
	var k5 float32 = 0.0314e+2
	message := fmt.Sprintf("k1:%g\n"+
		"k2:%g\n"+"k3:%g\n"+
		"k4:%g\n"+"k5:%g\n",
		k1, k2, k3, k4, k5,
	)
	fmt.Println(message)
    k6 := 3.1
    // 查看默认的类型
    fmt.Printf("%T", k6)
}
//打印结果
k1:3.14
k2:3.14
k3:3.1415926e+07
k4:3.141592654
k5:3.14
float64

// 小知识:
%e	科学计数法,如-1234.456e+78
%E	科学计数法,如-1234.456E+78
%f	有小数部分但无指数部分,如123.456
%F	等价于%f
%g	根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
%G	根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)

2.4 字符类型

2.4.1 字符类型

  1. 简介:GO语言中没有字符类型,要存储单个的字符一般使用byte 和uint 类型保存,Go中的字符使用的都是UTF-8编码。底层都是存储的unicode码值,存储的时候使用整数,打印的时候可以使用%c查看对应字符
  2. 实战操作:可以看到对应的数值通过%c打印出来就是字符,字符类型通过打印可以得到字符。这就是unicode码值和字符串的转换
package main

import "fmt"

func main() {
	var c1 int = '中'
	fmt.Println(c1)
	fmt.Printf("%c", c1)
	// 字符类型本质上就是一个整数
	var c2 int = 97
	fmt.Printf("%c\n", c2)
	// ascii 使用的是byte,但是如果是unicode那就需要使用int类型了
	// 想显示字符那就需要使用字符集进行
}
// 打印结果
20013
中a

在这里插入图片描述

  1. 查看字符编码的网址:http://www.mytju.com/classcode/tools/encode_utf8.asp
  2. unicode utf-8 gbk ascii 都是什么?这个网上也有,但这里大致介绍下
    (1)一开始计算机中只有英文,阿拉伯数字这种还有一些符号,计算机中无法存储这些符号于是使用了ascii码,就是使用0-255代替字符,比如97 代表a 98代表b
    (2)随着计算机的流行,越来越多的国家加入,所以适应每个国家的编码,其中中国制定了GB2312编码标准(后面为了适应繁体字有制定了GBK是对GB2312标准的扩展,兼容GB2312);小日子过得不错的日本人也制定了字符编码标准Shift_JIS和EUC-JP。欧巴韩国也制定了EUC-KR和KSX1001编码标准。各个国家各有一套标准,极大的不方便使用,后来联合国为了统一,于是乎制定出了unicode 编码标准。
    (3)Unicode 是为解决字符编码的多样性而设计的,旨在为世界上所有的字符提供一个唯一的标识符。它包含了几乎所有的字符,涵盖了世界上各种语言的文字、符号和标点符号。Unicode 为每个字符分配了一个唯一的代码点,可以通过不同的编码方案进行编码。
    (4)Unicode是一个字符编码标准,而存储Unicode字符到计算机中涉及使用不同的编码方式。UTF-8和GBK是两种常见的Unicode编码方式,UTF8存储方式使用变长编码就是说1-4个字节根据长度自动变化,而gbk使用固定长度2个字节,适配中文环境。
    具体可以看:https://zhuanlan.zhihu.com/p/38333902
    unicode 字符编码集: https://home.unicode.org/

2.4.1转义字符

  1. 简介:转义字符\ 将后面的字母表示为特殊含义
    在这里插入图片描述

  2. 实战测试


package main

import "fmt"

func main() {
	// \b 退格键盘
	fmt.Println("-你好\b中国=")
	// \n 换行
	fmt.Println("-你好\n中国=")
	// \r 光标回到开头
	fmt.Println("-你好\r中国=")
	// \t tab的作用
	fmt.Println("-你好\t中国=")
}

/*
输出结果:
-你好中国=
-你好
中国=
中国=
-你好   中国=
*/

2.5 布尔类型

  1. 简介
    1. 布尔类型也是bool类型,只有 true 和false 两个值
    2. 占用1个字节
    3. 适用于逻辑运算符
  2. 实战测试
package main

import "fmt"

func main() {
	// 布尔类型定义
	var status bool = true
	var is_false bool = false

	fmt.Println(status)
	fmt.Println(is_false)
	// 逻辑运算
	is_true := 5 > 8
	fmt.Println(is_true)
}

/*
true
false
false
*/

2.6 字符串类型

  1. 简介
    字符串就是一串字符类型比如 “nihao,zhongguo”
  2. 实战测试
    (1)由于go采用utf8 所以支持使用中文变量
    (2)字符串中如果有多行还有特殊字符那么可以使用反引号
    (3)字符串拼接使用 + +=
    (4)如果字符串过长,要使用加号保留在上一行的最后一个
package main

import "fmt"

func main() {
	var s1 string = "小日子过得不错的"
	fmt.Println(s1)
	var s2 string = "王侯将相,宁有种乎"
	fmt.Println(s2)
	// 中文变量
	var 爱好 = "爱好水果和爬山"
	fmt.Println(爱好)
	// 带有特殊字符的话,需要使用反引号
	var s3 = `中国阁雪云低,卷沙风急,
	惊雁失序。户掩寒宵,屏闲冷梦,
	灯飐唇似语。堪怜窗景,都闲刺绣,
	但续旧愁一缕。邻歌散,罗襟印粉,
	袖湿茜桃红露。
	西湖旧日,留连清夜,爱酒几将花误。
	遗袜尘销,题裙墨黯,天远吹笙路。吴
	台直下,缃梅无限,未放野桥香度。
	重谋醉,揉香弄影,水清浅处。`
	fmt.Println(s3)
	var s4 = "你好" + "给点知识" +
		"公众号你关注了了?" +
		"赶紧扫码关注下呢?"
	s4 += "感谢您的关注!!"
	fmt.Println(s4)
}

2.7 小结

  1. 在go中每个数据类型都有一个默认值,如果我们只是定义了 var age int; 没有给值得话,那么编译器都会给它们默认值;
  2. 实战测试
    (1)可以看到string默认值是空字符串,并不是空格
package main

import "fmt"

func main() {
    fmt.Println("Hello world!")
    var a1 int 
    var a2 string 
    var a3 uint
    var a4 byte
    var a5 bool
    fmt.Println(a1)
    fmt.Println(a2)
    fmt.Println(a2=="")
    fmt.Println(a3)
    fmt.Println(a4)
    fmt.Println(a5)
    
}
// 输出结果
Hello world!
0

true
0
0
false

在这里插入图片描述

2.8.数据类型转换

2.8.1 基本数据类型的转换

  1. 简介类型转换分为显式转换和隐式转换
    (1)显式转换:显式转换是指在代码中明确指定将一个数据类型转换为另一个数据类型的操作,使用显式的转换运算符或函数来完成。这种转换需要开发人员明确指定,并可能在类型转换过程中丢失一些数据或精度。例如,将一个浮点数转换为整数时,小数部分会被截断。
float a = 3.14;
int b = (int)a;  // 显式将浮点数转换为整数

(2)隐式转换:隐式转换是指在某些情况下,编程语言会自动将一个数据类型转换为另一个数据类型,而无需显式地指定转换操作。这种转换是编译器自动进行的,通常涉及数据类型之间的兼容性或类型提升的情况。例如,将一个整数赋值给一个浮点数变量,或将一个字符赋值给一个整数变量等。

int a = 5;
float b = a;  // 隐式将整数转换为浮点数

在Go使用隐式转换,会出现报错,编译都无法通过如下图:在这里插入图片描述

注意:GO语言中只有显式转换。
也就是:

package main

// 类型转换
import "fmt"

func main() {
	// 类型转换
	var a1 int = 100
	fmt.Println(a1)
	// 隐式转换 var a2 float32 = a1 这种方式转换是不行的
	var a2 float32 = float32(a1)
	// 注意:这里只是把a1 得值类型转为了float32
	// 而a1类型还是原来的int
	fmt.Printf("a1=%d,type=%T, a2=%f,type=%T",
		a1, a1, a2, a2)
	fmt.Println()
	// 将float64 转为int8 得时候 编译不会出错,但是会数据得溢出
	var a3 int64 = 99999
	// 因为类型不同所以溢出了
	var a4 int8 = int8(a3)
	fmt.Println(a3, a4)
	var a5 int32 = 88
	//  会直接溢出
	var a6 int8 = int8(a5) + 127
	//  编译不会通过
	var a7 int8 = int8(a5) + 128
	fmt.Println(a6)
	fmt.Println(a7)
}

/*
//1.编译不通过:var a7 int8 = int8(a5) + 128

# command-line-arguments
12.go\goproject\src\demo11\main.go:26:27: 128 (untyped int constant) overflows int8

//2.编译不通过给:注释掉以编译不通过的代码。输出结果:
100
a1=100,type=int, a2=100.000000,type=float32
99999 -97
-41

*/

2.8.2 基本数据类型和string类型的转换

  1. 转换方式简介
    (1)方法1:使用格式化方法转换:fmt.Sprint(“%参数”, 表达式);
    官方手册方法介绍:func Sprintf(format string, a …interface{}) string
    解释:
  • format string:这是一个格式字符串,用于指定输出的格式。格式字符串中可以包含普通文本和格式化动词(例如%d%s%f等),用于插入可变参数的值。格式化动词告诉Sprintf函数如何将参数转换为字符串并插入到格式字符串中。
  • a ...interface{}:这是可变参数列表,允许传递任意数量的参数。这些参数的类型可以是任何类型,因为它们的值将在运行时根据格式字符串的指示进行转换并插入到最终的字符串中。
    (2)方法2:使用strconv包的函数
  1. 实战测试
    (1)使用fmt.Sprintf(“%xx”, xx)
package main

// 2.8 数据类型转换
// 基本类型转为string类型

import "fmt"

func main() {
	// 整型转为字符串类型
	var age int = 19
	var s1 string = fmt.Sprintf("age=%d,type=%T", age, age)
	fmt.Println(s1)

	// 浮点型转为字符串类型
	var score float32 = 98.89
	s2 := fmt.Sprintf("score=%f, type=%T", score, score)
	fmt.Println(s2)

	// 布尔类型转为字符串类型
	var status bool = true
	s3 := fmt.Sprintf("status=%t, type=%T", status, status)
	s4 := fmt.Sprintf("%t", status)
	fmt.Println(s3)
	fmt.Println(s4 == "true")

	// 字符类型转为字符串类型
	var gender byte = 'm'
	s5 := fmt.Sprintf("gender=%c", gender)
	s6 := fmt.Sprintf("%c", gender)
	fmt.Println(s5)
	fmt.Println(s6 == "m")
	// 报错:main.go:32:20: invalid operation:
	// s6 == 'm' (mismatched types string and untyped rune)
	// 在Go语言中,'m'是一个字符字面量,表示一个单个的字符。
	// 而变量s6是一个字符串,因此在比较s6和'm'时会产生类型不匹配的错误。
	// fmt.Println(s6 == 'm')
}

// 输出结果:
age=19,type=int
score=98.889999, type=float32
status=true, type=bool
true
gender=m
true

(2)使用strconv:这块可以参考具体的文档,一般不使用这种方法转换

package main

import (
	"fmt"
	"strconv"
)

func main() {
	// 整型转字符串
	var age int = 18
	var s1 string = strconv.FormatInt(int64(age), 10)
	fmt.Printf("my age is %s", s1)
	fmt.Println()

	// 浮点类型转字符串
	var score float32 = 2.8
	// FormatFloat(要转换的值,)
	// func FormatFloat(f float64, fmt byte, prec, bitSize int) string
	var s2 string = strconv.FormatFloat(float64(score), 'f', 1, 32)
	fmt.Println(s2)
	// 布尔类型转字符串
	var status bool
	var s3 string = strconv.FormatBool(status)
	fmt.Println(s3)
}

2.8.3 string转基本类型

  1. 使用strconv 进行转换
    (1) 转整型
    strconv.ParseInt(“”)
package main

// 字符串转为基本类型

import (
	"fmt"
	"strconv"
)

func main() {
	var s1 string = "true"
	var b1 bool
	var err1 error
	// 这里返回两个值,所以使用两个参数
	b1, err1 = strconv.ParseBool(s1)
	fmt.Printf("b1=%t,type=%T, error=%s", b1, b1, err1)
	fmt.Println()
	// 我们也可以使用占位符 _ 来接收参数
	b1, _ = strconv.ParseBool(s1)
	fmt.Printf("b1=%t,type=%T", b1, b1)
	fmt.Println()

	// 整型转换 0x16 十进制=22
	var s2 string = "16"
	var i1 int64
	// 三个参数
	// 第一个是字符串 第二个是字符串的进制8进制
	i1, _ = strconv.ParseInt(s2, 8, 64)
	fmt.Printf("i1=%d", i1)
	fmt.Println()

	var s3 string = "128"
	var i2 int64
	// 三个参数
	i2, _ = strconv.ParseInt(s3, 0, 8)
	fmt.Printf("i1=%d", i2)
	// 直接转
	fmt.Println()

	var er error
	i2, er = strconv.ParseInt("112s23", 0, 8)
	fmt.Printf("i1=%d, er=%s", i2, er)
	// 直接转 16进制的16 10进制是22
	fmt.Println()
	i2, _ = strconv.ParseInt("0x16", 0, 8)
	fmt.Printf("i1=%d", i2)
}

// 输出结果
// b1=true,type=bool, error=%!s(<nil>)
// b1=true,type=bool
// i1=14  // 字符串16是8进制,所以10进制表示就是14
// i1=127  // 128是十进制 但是第三个参数是8bit 溢出了,所以是127
// i1=0, er=strconv.ParseInt: parsing "112s23": invalid syntax
// i1=22

总结:

  1. 使用 var err1 error 可以定义一个接收返回值错误的类型
  2. strconv.ParseInt(字符串, 字符串的进制, 要转成的类型)
  3. strconv.ParseBool(字符串)
  4. 其他类型的转换可以参考手册
  5. 如果转换失败则会被赋值为默认值

2.9 指针

  1. 简介:指针就是指向地址的变量
    (1)我们定义的变量编译器再执行的时候都会给变量在内存中给它申请一个空间,这个空间有对应的地址,我们用来存储这个地址的变量就叫做指针
    (2)定义指针使用*类型 比如*int 即可
    var ptr1 *int
    var ptr2 *float32
    var ptr2 *float64
    在这里插入图片描述

  2. 实战测试
    (1)取出对应的指针地址使用&

var age int = 19
var *ptr *int = &age

(2)* 根据地址取出对应的值使用星

var *ptr *int = &age 
fmt.Println(*ptr)

完成代码如下:

package main

// 指针类型

import "fmt"

func main() {
	var age int = 22
	var ptr *int = &age
	var ptr1 **int = &ptr
	fmt.Println("age 的地址是", &age)
	fmt.Printf("age=%d,ptr=%v", age, ptr)
	fmt.Println()
	fmt.Println("使用指针打印出值:", *ptr)
	fmt.Println("ptr指针的地址:", &ptr)
	fmt.Println("ptr1指针的地址:", &ptr1)
}
输出结果:
// age 的地址是 0xc00000a0c8
// age=22,ptr=0xc00000a0c8
// 使用指针打印出值: 22
// ptr指针的地址: 0xc00006c020
// ptr1指针的地址: 0xc00006c028
  1. 其他知识
    (1)可以通过指针进行赋值,修改值
    修改方法就是直接给指针赋值即可,例如: ```
var name string = "张三"
ptr *string = &name
*ptr = "里斯"

完整代码演示如下:

package main

// 通过在指针修改值

import "fmt"

func main() {
	// 通过在指针修改值
	var name string = "张三"
	var ptr2 *string = &name
	fmt.Printf("name的初始值是:%v", name)
	fmt.Println()
	fmt.Printf("ptr2指针地址是:%v, 值是:%v", ptr2, *ptr2)
	fmt.Println()
	fmt.Println("------分割线------")
	// 修改值
	*ptr2 = "里斯"
	fmt.Printf("ptr2修改值后name的值是:%v", name)
	fmt.Println()
	fmt.Printf("ptr2修改值后的地址:%v, 值是:%v", ptr2, *ptr2)
}
输出结果:
//name的初始值是:张三
//ptr2指针地址是:0xc00008a030, 值是:张三
//------分割线------
//ptr2修改值后name的值是:里斯
//ptr2修改值后的地址:0xc00008a030, 值是:里斯

(2)指针变量接收的一定是地址值
一旦赋值的是其他类型就会报错,这里很好理解,就是ptr2本来是指针类型,你非要赋值其他类型肯定会报错的。所以这里我们要赋值对应的类型的值。
在这里插入图片描述

(3)指针变量的地址必须匹配对应的类型。基本数据类型,都有对应的指针类型,形式为数据类型,比如int的对应的指针就是int float32对应的指针就是*int float32对应的就是*float32。要不然会报错,如下:

var ptr *int 
var socre float32 = 98.9
ptr = &score

报错内容:main.go:31:18:在变量声明中,不能使用 &socre(*float32 类型的值)作为 *int

在这里插入图片描述

3.关键词与预定义的标识符

3.1 关键字

#GO语言关键字

  1. 共有25个关键字
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

3.2 预定义标识符

#GO语言标识符

  1. 36个预定标识符
append          bool        byte         cap       close           
complex         complex64   complex128   copy      true
uint            uint8       uint16       uint32    uint64
int             int8        int16        int32     int64
float32         float64     make         new
imag            iota        len          nil    
print           println     panic        uintprt
real            recover     string       flase

4.点点答题

  1. 个人信息;
  • 难度:入门;
  • 描述信息:
    每个人都有姓名,年龄,性别,用三个变量,类型分别是string,int,bool,来表示人的这三个基本信息。然后按照,姓名,年龄,性别的顺序进行输出打印。
  • 输入:空
  • 输出:空 0 false
  • 示例
package main
import  "fmt"
func main() {
  var name string
  var age int
  var gender bool
  fmt.Println(name)
  fmt.Println(age)
  fmt.Println(gender)
}
  1. 指针使用(此题目来源于:牛客网)
描述
给定两个变量a,b,判断两个变量的地址,值(a,b的地址取得)是否相等,将结果依次存入切片,并返回。
知识点:
Go语言中的指针操作非常简单,只需要记住两个符号:&(取地址)和*(根据地址取值)。

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用&字符放在变量前面对变量进行“取地址”操作。 Go语言中的值类型(int、float、boolstring、array、struct)都有对应的指针类型,如:*int*int64*string等。
示例1
输入:
1,2
复制
返回值:
[false,false]

-----------参考答案
package main

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param a int整型 变量a
 * @param b int整型 变量b
 * @return bool布尔型一维数组
*/
func equal( a int ,  b int ) []bool {
    // write code here
    result := []bool{&a==&b, a==b}
    return result
}

5.小知识以及总结

5.1总结

1.fmt.Sprintf与fmt.Sprint的区别

  • fmt.Sprintf的返回值是一个格式化后的字符串。
  • fmt.Sprint的返回值是将输入参数转换为字符串后连接在一起的结果。
package main

// 2.8 数据类型转换
// 基本类型转为string类型

import "fmt"

func main() {
	// 整型转为字符串类型
	var age int = 19

	// 字符类型转为字符串类型
	var gender byte = 'm'
	s6 := fmt.Sprintf("%c", gender)
	s7 := fmt.Sprint("My age is ", s6, " and I am ", age, " years old.")
	fmt.Println(s7)
}
// 输出结果
My age is m and I am 19 years old.

下一个文章:
大致内容:一二章节总结和GO语言基础题目

文章来源:https://blog.csdn.net/weixin_44331765/article/details/135719264
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。