Go之入门(特性、变量、常量、数据类型)
一、Go语言特性
- 语法简单
- 并发性。Go语言引入了协程goroutine,实现了并发编程
- 内存分配。Go语言为了解决高并发下内存的分配和管理,选择了tcmalloc进行内存分配(为了并发设计的高性能内存分配组件,使用cache为当前线程提供无锁分配,多个central在不同线程间平衡内存单元复用。在更高层次,heap管理大块的内存分配,用以切片成不同等级的复用内存块。快速分配和二级平衡机制,可以更高性能的进行内存分配)
- 垃圾回收。在Go中指针的运算被阻止,故垃圾回收会容易点
- 静态链接。Go的便衣只需要编译后的一个可执行文件(将运行时依赖的库直接打包到可执行文件内部),无需附加任何东西,就能部署
- 标准库。Go的标准库比较丰富
- 工具链。无论是编译、格式化、错误检查、帮助文档还是第三方包下载更新都能有对应的工具
二、Go的变量
1.变量的声明
- Go是静态语言,因此其变量必须要有明确的类型,这样编译器才能检查变量正确性
- 声明变量语法:
var 变量名 变量类型//举例:声明两个变量都为int指针类型var a, b *int
(1) 变量的声明
- 当一个变量被声明后,系统会自动初始化一个值。int类型初始值为0,float类型初始值为0.0,bool类型初始值为false,string类型初始值为空字符串,切片、函数、指针类型初始值为nil
- 变量命名遵循驼峰命名法,即首个单词小写,每个新单词首字母大写。如GoStudy
- 批量声明变量的格式:
//方式一:使用关键字var和花括号{},可以将一组变量定义放在一起var{a intb stringc byted []float32e func()boolf struct{x int}}//方式二:把变量定义和初始化放在一起:名字 := 表达式。//但这种方式有以下限制:1.不能提供数据类型;2.只能用在函数内部func main(){x := 10a, s := 1, "abc"}
2.变量的初始化
- 当一个变量被声明后,系统会自动初始化一个值。int类型初始值为0,float类型初始值为0.0,bool类型初始值为false,string类型初始值为空字符串,切片、函数、指针类型初始值为nil
(1) 变量初始化语法
//方式一:var 变量名 类型 = 表达式var a int = 10//方式二:省略其类型,采用编译器推导类型的格式L:var 变量名 = 表达式var a = 10//方式三:更精简的写法,省略关键字var: 变量名 := 表达式a := 10//注意:1.由于使用了:=,而不是=,因此方式三的写法的左边变量名必须是没有定义过的变量,若该变量定义过,则编译器会报错2.在多个短变量声明和复制中,至少又一个新声明的变量出现在左值中,即使其他变量名可能是重复声明的,编译也不会出错,如下所示:res1, err := MyTest(2)res2, err := MyTest(3)
(2) 多重赋值
- Go语言的多重赋值,用于变量值的互换
/*var a int = 100var b int = 200a, b = b, a*/package mainimport "fmt"func main(){var a int = 100b := 200fmt.Println("a = ", a," b = ", b)b, a = a, bfmt.Println("a = ", a," b = ", b)}
结果:
3.匿名变量
- Go语言中支持没有名称的变量、类型或者方法,这些统称为匿名变量,匿名变量是为了增强代码的灵活性
- 匿名变量是一个下划线"_"(被称为空白标识符),_可以像其他标识符一样用于变量的声明或者赋值(任何类型都可以赋值给它),但一旦赋值给这个标识符的值都会被抛弃,因此这些值无法在后续代码中使用
- 匿名变量,没有内存空间,不会给它分配内存
package mainimport "fmt"func GetTheData()(int, int){a := 200b := 300return a, b}func main(){a, _ := GetTheData()_, b := GetTheData()fmt.Printf("a=%d, b=%d",a, b)}
结果:
4.变量作用域
- 局部变量:函数内定义的变量,作用域是函数体内,函数调用结束后,变量会被销毁。形参的作用域跟局部变量一样。
- 全局变量:函数外定义的变量,全局变量的声明必须用关键字var。若全局变量和局部变量同名,在函数内以局部变量为准。
三、Go的常量和const
- 和C++一样,Go中是用const关键字来定义常量,常量是在编译时创建的,值在创建后就不会改变
//常量的声明const a = 3.1415926//常量的批量声明const{b = 2.12345c = 1.23455}
1.无类型常量
- Go语言中有个与其他语言不一样的地方,虽然一个常量可以是任意一个明确的基础类型的值,例如,可以是int类型的值或者string类型的值;但许多常量没有一个明确的基础类型
//math.Pi可无类型的浮点数常量,可直接用于任意需要浮点或者复数的地方var x float32 = math.Pivar y complex128 = math.Pivar z float64 = math.Pi
- 若math.Pi已经被确定为特定类型之后,那么结果的精度可能不一样。若需要一个精确的值,则需要进行显式类型转换
const Pi float64 = math.Pivar x float32 = Pi //x的精度就会改变var y float32 = (float32)Pi //y进行了类型转换,精度不会变var z complex128 = (complex128)Pi //z进行了类型转换,精度不会变
四、Go的数据类型
1.Go的基本数据类型
类型名 | 含义 |
---|---|
bool | 布尔型,true、false |
string | 字符串类型 |
int、int8、int32、int64 | 有符号整型 |
uint、uint8、uint16、uint32、uint64、uintptr | 无符号整型 |
byte | 字符类型 |
rune | 字符类型 |
float32、float64 | 浮点型 |
complex64、complex128 | 复数类型 |
2.整型
(1) 有符号整型
- int8表示8位有符号整型,范围是-128~127
- int16表示16位有符号整型,范围是-32768~32767
- int32表示32位有符号整型,范围是-2147483648~2147483647
- int64表示64位有符号整型,范围是-9223372036854775808~9223372036854775807
- int根据编译器和计算机硬件的不同数值大小不同,在32位机器中为32位=4字节,在64位机器中位64位=8字节
(2) 无符号整型
- uint8表示无符号8位,范围是0~255
- uint16表示无符号16位,范围是0-65535
- uint32表示无符号32位,范围是0~4294967295
- uint64表示无符号64位,范围是0~18446744073709551615
- uint:根据不同的底层平台,32 位系统是32位,64 位系统是64位
3.浮点型
- float32:32位浮点型
- float64:64位浮点型
4.布尔类型
- 布尔类型的值只有两种:true或false,默认是false
- 布尔类型无法参与数值运算,也无法与其他类型进行转换
5.复数类型
- 复数是有两个浮点数组成,一个是实部,一个是虚部。
- 复数的类型有两种:complex128(64位实数和虚数)和complex64(32位实数和虚数),复数的默认类型是complex128
- 复数也可以用 == 和 != 进行相等比较,只有两个复数的虚部和实部都相等时,它们才相等
- 复数的声明方式:
//var name complex128 = complex(x,y)package mainimport "fmt"func main(){var x complex128 = complex(1,2) //1 + 2ivar y complex128 = complex(3,4) //3 + 4ifmt.Println(x * y)fmt.Println(real(x * y))fmt.Println(imag(x * y))var z complex128 = complex(-5,10)var w complex128 = complex(5,10)fmt.Println(x * y == z)fmt.Println(x * y == w)}
结果:
6.字符类型
- Go语言中字符类型有以下两种:
(1)一种是uint8类型即byte类型,代表一个ASCII码字符
(2)另一种是rune类型,代表一个UTF-8字符,当需要处理中文、日文或其他字符时,则需要用到rune类型。等价于int32类型 - byte类型时uint8的别名,使用举例:var ch byte = ‘A’
- 在ASCII码中,A的值时65,使用16进制表示为41,故下面写法是等效的:var ch byte = 65 或 var ch byte = ‘\x41’
- Go语言支持UTF-8即Unicode字符,该字符称为Unicode代码点或者runes,并在内存中用int来表示,一般使用格式U+hhhhh,其中h表示一个16进制数
- 在书写Unicode字符时,需要在16进制数前加上\u或者\U。若需要使用到4字节,则使用\u前缀;若需要使用到8字节,则使用\U前缀。
package mainimport "fmt"func main(){var ch int = '\u0041'var ch2 byte = 'A'var ch3 int = '\U00000061'fmt.Println(ch, ch2, ch3)fmt.Printf("ch=%c, ch2=%c, ch3=%c", ch,ch2,ch3)}
结果:
- Unicode包中内置了一些用于测试字符的函数,这些函数的返回值都是一个布尔值,如下:
(1)判断是否是字母:unicode.IsLetter(ch)
(2)判读是否是数字:unicode.IsDigit(ch)
(3)判断是否为空白字符:unicode.IsSpace(ch)
package mainimport ("fmt""unicode")func main(){var ch rune = 'A'var gi rune = '1'var sp rune = ' 'fmt.Println(unicode.IsLetter(ch))fmt.Println(unicode.IsLetter(gi))fmt.Println(unicode.IsDigit(ch))fmt.Println(unicode.IsDigit(gi))fmt.Println(unicode.IsSpace(sp))}
结果:
7.字符串类型
- Go语言中字符串的内部实现使用UTF-8编码,通过rune类型,可以方便地对每个UTF-8字符进行访问。Go也支持按照传统地ASCII码地方式逐字符进行访问
- 可以用反引号’'来定义多行字符串
package mainimport ("fmt")func main(){const str = `aaaabbbbccccdddd`fmt.Println(str)}
结果:
8.数据类型转换
- Go语言不存在隐式类型转换,因此类型转换必须要显式的声明:valueOfTypeB = typeB(valueOfTypeA)
package mainimport ("fmt""math")func main(){fmt.Println("int range:", math.MinInt, math.MaxInt)fmt.Println("int8 range:", math.MinInt8, math.MaxInt8)fmt.Println("int16 range:", math.MinInt16, math.MaxInt16)fmt.Println("int32 range:", math.MinInt32, math.MaxInt32)fmt.Println("int64 range:", math.MinInt64, math.MaxInt64)var a int32 = 912345678//将a转换为十六进制,会发生数值截断fmt.Printf("int32:0x%x, %d\n", a,a)var pi float32 = 3.14fmt.Println(pi)fmt.Println(int(pi))}
结果:
9.指针
- 指针在Go语言中可被拆分成两个核心概念:
(1)类型指针,允许对这个指针类型的数据进行修改,传递数据可以使用指针,而不需要进行数据之间的拷贝。类型指针不能进行偏移和运算。
(2)切片,由指向起始元素的原始指针、元素数量和容量组成 - 指针相关的概念:指针地址、指针类型、指针取值
(1) 指针地址和指针类型
- 指针就是存放变量的地址,一个指针变量可以指向任何一个值的内存地址。按照编译器的不同在32bit和64bit机器上,指针大小不一样,在32位机器上指针的大小为4字节,在64位机器上指针的大小为8字节。默认值为nil。缩写为ptr。
- 每个变量都有一个地址,跟c++一样,&为取地址操作符,若想获取这个变量的地址,用&即可。*为解引用操作符,可以获取到指针所指向的地址中存的值。
- 指针的类型为T
package mainimport "fmt"func main(){a := 100b := 'a'c := "hello world"fmt.Printf("a的地址是%p, b的地址是%p,c的地址是%p\n", &a, &b, &c)aptr := &abptr := &bcptr := &cfmt.Printf("a的地址是%p, b的地址是%p,c的地址是%p\n", aptr, bptr, cptr)fmt.Println("a的值是", *aptr)fmt.Printf("b的值是%c\n", *bptr)fmt.Println("c的值是", *cptr)//指针的类型fmt.Printf("aptr的类型是%T\n", aptr)fmt.Printf("bptr的类型是%T\n", bptr)fmt.Printf("cptr的类型是%T\n", cptr)}
结果:
- 创建指针的另一种方法:new()函数,new(类型)
package mainimport "fmt"func main(){iptr := new(int)stptr := new(string)*iptr = 100*stptr = "hello world"fmt.Println("*iptr=",*iptr)fmt.Println("*stptr=",*stptr)a := 200*iptr = afmt.Println("*iptr=",*iptr)}
结果:
10.类型别名type关键字
(1) 类型别名
- Go中的类型别名的出现主要是为了解决代码升级时,迁移中存在的类型兼容性问题。在C++中,代码重构升级可以用宏快速定义一段新的代码,而Go语言中没有宏的概念。
- 写法:type int = rune
- 类型别名与类型定义表面上看只有一个等号的差异,实际区别如下:
package mainimport "fmt"type NewInt int //类型定义type IntNew = int //类型别名func main(){var a NewInt //使用类型定义,定义的新类型fmt.Printf("a的类型为:%T\n",a)var b IntNew //使用类型别名,定义的新类型fmt.Printf("b的类型为:%T\n",b)}
结果:
上述结果不难发现,a的类型是main.NewInt,即main包下定义的NewInt类型;b的类型还是int类型。而IntNew该类型只会在代码中存在,编译完成后就不会存在。
(2) 类型别名和类型定义的区别
- 类型定义:
(1)一个新定义的类型与源类型是两个不同的类型
(2)一个新定义的类型与源类型底层的类型是一样的,但是不能进行直接的赋值,可以进行显式的类型转换
(3)类型定义可以出现在函数体里
package mainimport "fmt"func main(){type NewInt int //类型定义var a NewInt = 100 //使用类型定义,定义的新类型var b int = 200var c int = 300fmt.Println("a的值为", a)fmt.Println("b的值为", b)fmt.Println("c的值为", c)b = int(a)a = NewInt(c)fmt.Println("a的值为", a)fmt.Println("b的值为", b)fmt.Println("c的值为", c)}
结果:
- 类型别名:
(1)类型别名与源类型是同一种类型
(2)类型别名与源类型之间可以进行直接的赋值
package mainimport "fmt"func main(){type IntNew = int //类型别名var a IntNew = 100 //使用类型别名,定义的新类型var b int = 200var c int = 300fmt.Println("a的值为", a)fmt.Println("b的值为", b)fmt.Println("c的值为", c)b = a //类型别名与源类型就是同一类型,故可以直接相互赋值a = cfmt.Println("a的值为", a)fmt.Println("b的值为", b)fmt.Println("c的值为", c)}
结果:
相关文章:

Go之入门(特性、变量、常量、数据类型)
一、Go语言特性 语法简单并发性。Go语言引入了协程goroutine,实现了并发编程内存分配。Go语言为了解决高并发下内存的分配和管理,选择了tcmalloc进行内存分配(为了并发设计的高性能内存分配组件,使用cache为当前线程提供无锁分配…...

第九届省赛——8等腰三角形(找规律)
题目:本题目要求你在控制台输出一个由数字组成的等腰三角形。具体的步骤是:1. 先用1,2,3,...的自然数拼一个足够长的串2. 用这个串填充三角形的三条边。从上方顶点开始,逆时针填充。比如,当三角形高度是8时:…...

【产品设计】ToB 增删改查显算传
入职培训时技术leader说:“我不需要你们太聪明,做好基础的增删改查就可以了。”看似很简单的活,要做好并不容易。基础的坑在哪里呢? 一、 增(新增、创建、导入) 1. 明确表字段类型 新增的业务是由不同类型…...

MySQL(二)视图、锁、存储过程、触发器、锁以及常用工具
MySQL进阶视图检查选项视图的更新存储过程存储过程基本语法变量系统变量用户自定义变量局部变量if判断参数casewhile循环repeat循环loop循环cursor游标handler条件处理程序存储函数触发器锁全局锁表级锁表锁元数据锁意向锁行级锁行锁间隙锁&临键锁InnoDB引擎逻辑存储结构事…...

CorelDRAW Graphics Suite2023更新内容介绍
懂设计的职场人都知道这款软件,CorelDRAW是一款非常高效的矢量图形设计软件。CorelDRAW操作界面简洁易懂,能够为用户提供精确地创建物体的尺寸和位置的功能,减少点击步骤,提高设计效率,节省设计时间。功能比普通的美图…...
2021牛客OI赛前集训营-提高组(第三场) T1变幻
2021牛客OI赛前集训营-提高组(第三场) 题目大意 对于一个大小为nnn的数组aaa的任意一点iii,若满足ai−1>aia_{i-1}>a_iai−1>ai且ai<ai1a_i<a_{i1}ai<ai1,则称iii为山谷点。111和nnn不可能为山谷点。…...

你还在使用if-else写代码吗,今天带你领略下策略模式的魅力!
1、什么是策略模式 策略模式其实也是在解耦,把策略的定义、创建、使用这三个部分解耦开来,因为本身策略模式也是基于接口编程,这样其实可以简单的理解客户端调用使用接口进行编程,可以通过工厂方法创建对应的策略模式,…...

Leetcode. 21 合并两个有序列表
尾插 核心思路:依次比较 ,取经过比较后较小值进行尾插 cur1 指向list1 ,cur 2指向list2 ,当cur1走完list1 或者cur2 走完list2 后停止 如果cur1走完list1 ,可以将cur2 整个拿下来尾插 如果cur2走完list2 ,可以将cur1 整个拿下来尾插 特殊情况 ࿱…...

使用 Wall 教你搭建 照片墙 和 视频墙
下载 Github:https://github.com/super-tongyao/wall 国内仓库(不推荐,只做加速访问,无编译包和发行版,以github仓库为准):https://gitee.com/Super_TongYao/wall 推荐github仓库,下载最新版…...

0103 MySQL06
1.事务 1.一个事务其实就是一个完整的业务逻辑 如:转账,从A账户向B账户转账10000,将A账户的钱减去10000(update),将B账户的钱加上10000(update),这就是一个完整的业务逻…...

【UE4 RTS游戏】04-摄像机运动_鼠标移动到视口边缘时移动Pawn
效果可以看到当鼠标移动到视口边缘时,Pawn就会向这个方向移动。步骤打开项目设置,添加两个操作映射打开“CameraPawnController”,在事件图表中添加两个浮点型变量,一个为公有一个为私有。分别命名为“ZoomSensitivity”、“MaxAr…...

147597-66-8,p-SCN-Bn-NOTA,NOTA-P-苯-NCS新型双功能螯合剂
p-SCN-Bn-NOTA | NOTA-P-苯-NCS | CAS:147597-66-8 | 纯度:95%1.p-SCN-Bn-NOTA试剂信息:CAS号:147597-66-8外观:白色固体分子量:C20H26N4O6S分子式:448.4928溶解性:溶于有机溶剂&…...

JDK解压安装及idea开发工具配置
1. 安装JDK 1.1 下载安装包 下载安装包,直接解压,注意,解压的路径不要有中文 1.2 配置环境变量 右键点击我的电脑,选择属性 选择高级系统设置 选择环境变量 选择新建 在变量名中输入JAVA_HOME,变量值就是1.1中压缩包…...

使用Ubuntu中的Docker部署Remix
一、简介1.博主这里使用的是腾讯云的服务,然后使用Docker进行部署Remix。2.踩了几个坑,没有花费过多时间,所以这篇文章会记录踩过的坑。然后避免你们掉进去,然后花费过多时间。3.这里就不写怎么安装Docker了,因为博主上…...
【MySQL】P9 多表查询(3) - 子查询
子查询子查询基本概念(公式)子查询分类按照结果分类标量 子查询列 子查询行 子查询表 子查询子查询 基本概念(公式) SQL查询语句中嵌套Select语句,称为嵌套查询,亦称为子查询; select * from…...

SpringMVC中的拦截器不生效的问题解决以及衍生出的WebMvcConfigurationSupport继承问题思考
文章目录SpringMVC中的拦截器不生效的问题解决WebMvcConfigurationSupport继承问题思考SpringMVC中的拦截器不生效的问题解决 过滤器代码(被Spring扫描并管理): Component public class StuInterceptor implements HandlerInterceptor {Overridepublic boolean pr…...

【量化交易笔记】3.实现数据库保存数据
上一节,我们通过下载相关的 pandas 数据保存为 本地csv文件,这一节将上节的数据以数据库方式保存。 数据库保存 采集数据部分前一节已做说明,这里就直接用采用前面的内容。这里着重说明的事数据库连接。对与 python 相连接的数据库有很多&a…...

[数据结构]:15-堆排序(顺序表指针实现形式)(C语言实现)
目录 前言 已完成内容 堆排序实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-PSeqListFunction.cpp 04-SortCommon.cpp 05-SortFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容,除其中使用到C引用外,全为C语言代码…...
蓝桥 卷“兔”来袭编程竞赛专场-02破解曾公亮密码 题解
赛题介绍 挑战介绍 曾公亮编撰的《武经总要》中记载了一套严谨的军事通信密码,这也是目前发现我国古代战争中最早使用的军用密码表。将战场上可能常用到的情况,用 40 个短语归纳表示,且每个短语前编有固定的数字代码,这 40 个短…...

CSS定位
🍓个人主页:bit.. 🍒系列专栏:Linux(Ubuntu)入门必看 C语言刷题 数据结构与算法 HTML和CSS3 目录 1.1为什么需要定位? 1.2定位组成 1.3静态定位static(了解) 1.4相对定位 relative …...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...

性能优化中,多面体模型基本原理
1)多面体编译技术是一种基于多面体模型的程序分析和优化技术,它将程序 中的语句实例、访问关系、依赖关系和调度等信息映射到多维空间中的几何对 象,通过对这些几何对象进行几何操作和线性代数计算来进行程序的分析和优 化。 其中࿰…...
C/Python/Go示例 | Socket Programing与RPC
Socket Programming介绍 Computer networking这个领域围绕着两台电脑或者同一台电脑内的不同进程之间的数据传输和信息交流,会涉及到许多有意思的话题,诸如怎么确保对方能收到信息,怎么应对数据丢失、被污染或者顺序混乱,怎么提高…...
qt 双缓冲案例对比
双缓冲 1.双缓冲原理 单缓冲:在paintEvent中直接绘制到屏幕,绘制过程被用户看到 双缓冲:先在redrawBuffer绘制到缓冲区,然后一次性显示完整结果 代码结构 单缓冲:所有绘制逻辑在paintEvent中 双缓冲:绘制…...