Go基础语法:基本数据类型

2023-09-20 19:30:00

3 基本数据类型

基本数据类型包括:整型、浮点型、布尔型、字符串。

除以上基本类型之外,还有 数组、切片、结构体、函数、map、通道 等。

3.1 整型

3.1.1 整型

整型分为:int8int16int32int64 ,以及对应的无符号整型:uint8uint16uint32uint64

其中 unit8 对应其他语言中的 byte 类型;int16 对应 C 语言中的 short 类型;int64 对应 C 语言中的 long 类型。

各数据类型及对应的取值关系如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特殊整型:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意: 获取对象的长度时,内建的 len() 函数返回的长度可以根据不同平台的字节长度进行变化。实际使用中,切片或 map 的元素数量等都可以直接使用 int 来表示 。

3.1.2 八进制和十六进制

package main

import (
	"fmt"
)

func main() {
	// 声明十进制数.
	var a = 10
	// %d 为十进制数的占位符,表示输出十进制数——10
	fmt.Printf("%d \n", a)
	// %b 为二进制数的占位符,输出二进制数——1010
	fmt.Printf("%b \n", a)
	// %o 为八进制数的占位符,输出八进制数——12
	fmt.Printf("%o \n", a)
	// %x 为十六进制数的占位符,输出十六进制数——a
	fmt.Printf("%x \n", a)
	// %T 表示获取某个变量的类型_int
	fmt.Printf("%T \n", a)

	// 声明八进制数,以 0 开头
	b := 077
	// 63
	fmt.Printf("%d \n", b)
	//111111
	fmt.Printf("%b \n", b)
	// 77
	fmt.Printf("%o \n", b)
	// 3f
	fmt.Printf("%x \n", b)
	// int
	fmt.Printf("%T \n", b)

	// 声明 16 进制数,以 0x开头
	c := 0xff
	// 255
	fmt.Printf("%d \n", c)
	// 11111111
	fmt.Printf("%b \n", c)
	// 377
	fmt.Printf("%o \n", c)
	// ff
	fmt.Printf("%x \n", c)
	// int
	fmt.Printf("%T \n", c)

	// 显示声明为 int8 类型,否则,默认 int 类型
	d := int8(9)
	// 9
	fmt.Printf("%d \n", d)
	// 1001
	fmt.Printf("%b \n", d)
	// 11
	fmt.Printf("%o \n", d)
	// 9
	fmt.Printf("%x \n", d)
	// int8
	fmt.Printf("%T \n", d)

	// %v 表示获取某个变量的值——int8,9
	fmt.Printf("d 的类型为:%T,值为: %v", d, d)
}

3.2 浮点型

go 语言支持两种浮点型数,float32float64.

这两种浮点型数据格式遵循 IEEE 754 标准, float32 的浮点数的最大范围约为 3.4e38 ,可以使用常量定义:math.MaxFloat32。float64 的浮点数的最大范围约为 1.8e308, 可以使用常量定义 math.MaxFloat64

package main

import (
	"fmt"
	"math"
)

func main() {
	// %f 为浮点数的占位符,
	fmt.Printf("%f \n", math.MaxFloat32)
	fmt.Printf("%f \n", math.MaxFloat64)

	var a = 1.2345
	// 默认 floa64
	fmt.Printf("%T \n", a)

	var b = float32(1.2345)
	// 显示声明为 float32
	fmt.Printf("%T \n", b)
}

3.3 复数

  • 复数实际上是有两个实数(浮点数)的组合,一个表示实部(real),一个表示虚部(imag)。
  • 虚部需要添加 i 作为后缀。
  • real(复数)可以获取实部 ,imag(复数) 可以获取虚部
  • complex64complex128 两种类型,complex64 的实部和虚部为 32 位,complex128 的实部和虚部为 64 位。
package main

import "fmt"

func main() {
	// 1、声明一个复数
	var v1 complex64
	// 虚部数据需要后缀 i
	v1 = 3.2 + 12i
	fmt.Println("v1=", v1)

	// 2、自动推导类型的复数
	v2 := 3.3 + 2.0i
	fmt.Printf("v2的类型为:%T \n", v2)
	fmt.Println("v2的值为:", v2)

	// 3、获取复数的实部和虚部: real(复数),imag(复数)
	fmt.Println("v2的实部为:", real(v2), "v2的虚部为:", imag(v2))
}

运行结果:

cnpeng$ go run Day1.go 
v1= (3.2+12i)
v2的类型为:complex128 
v2的值为: (3.3+2i)
v2的实部为: 3.3 v2的虚部为: 2

3.4 布尔类型

3.4.1 布尔类型

go 语言中以 bool 声明布尔类型数据。布尔类型仅有 truefalse 两种值。

注意:

  • 布尔类型变量的默认值为 false
  • go 语言中不允许将整型强制转换为布尔类型
  • 布尔型数据无法参与数值运算,与无法与其他类型进行转换。

3.4.2 补充:格式化输出的总结

fmt 包的 Printf() 格式化输出可以使用下面的格式化符号:

格式含义
%%% 字面量
%b二进制整数值(基数为2),或者是(高级的)用科学计数法表示的指数为2的浮点数
%c字符型。可以把输入的数字按照 ASCII 码转换为对应的字符。
%d十进制数值(基数为10)
%e以科学计数法 e 表示的浮点数或者复数值
%E以科学计数法 E 表示的浮点数或者复数值
%f以标准计数法表示的浮点数或者复数值
%g%e或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出
%G%E或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出
%o以八进制表示的数字
%p以十六进制表示的值的地址,前缀为 0x, 字母使用小小的 a-f 表示
%s字符串
%t以 true 或者 false 输出布尔值
%T获取数据类型。
%U用 Unicode 表示法表示的整型码点。默认值为四个数字字符
%v使用默认格式输出的内置或自定义类型的值。或者时使用期望类型的 String() 方式输出的自定义值。
%#v如果输出的字符串,该字符串会被双引号包裹起来
%x以十六进制表示的整型值, a-f 使用小写
%X以十六进制表示的整型值, A-F 使用大写
package main

import (
	"fmt"
)

func main() {
	var str = "abc"
	// "abc" 
	fmt.Printf("%#v \n", str)
}

3.4 字符串

go 语言中的字符串以原生数据类型出现,使用字符串就想使用其他原生数据类型(int、bool、float32、float64 等)一样。

go 语言中字符串的内部实现使用了 UTF-8 编码。字符串的值使用双引号 " " 包裹( go 语言中,只有使用单引号 ' ' 包裹的是字符)。

3.4.1 字符串转义符

转义符含义
\r回车符(返回行首)
\n换行符
\t制表符
\'单引号
\"双引号
\\反斜杠

1字节=8Bit ,即1字节表示八个二进制位,也就是 八个 01——01010101
一个 UTF-8 编码的汉字通常占用三个字节,偏僻字可能会占四个字节。

package main

import (
	"fmt"
)

func main() {
	// 打印 windows 下的一个文件目录,需要使用转义字符
	// 输出结果:"D:\Go\src\code.github.cnoeng\stu"
	fmt.Printf("\"D:\\Go\\src\\code.github.cnoeng\\stu\"")
}

3.4.2 多行字符串(原样字符串)

go 语言中要定义一个多行字符串时,使用 反引号 (即键盘左上角数字一左侧的那个按键) 包裹。也叫原样字符串,输入啥样,输出就啥样。

package main

import (
	"fmt"
)

func main() {
	s := `
		床前明月光,
		疑是地上霜。
		举头望明月,
		低头思故乡。
	`
	fmt.Printf("%s \n", s)
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package main

import (
	"fmt"
)

func main() {
	s := `D:\Go\src\code.github.cnoeng\stu`
	// D:\Go\src\code.github.cnoeng\stu 
	fmt.Printf("%s \n", s)
}

3.4.3 字符串的常用操作

方法含义
len(str)获取字符串的长度
+ 或 fmt.Sprintf()拼接字符串
strings.Split分割
strings.contains判断是否包含
strings.HasPrefixstrings.HasSuffix前缀、后缀的判断
strings.Index()strings.LastIndex()子串出现的位置
strings.Join(a[]string,sep string)join 操作 (拼接)

字符串是由 byte 字节组成,所以字符串的长度就是 byte 字节的长度。

package main

import (
	"fmt"
	"strings"
)

func main() {
	s := `张三`
	// 6 
	fmt.Println(len(s))
	
	// 字符串拼接
	s1 := "李四"
	// fmt.Printf 只能输出到终端
	// 张三李四
	fmt.Printf("%s \n", s+s1)
	// 张三李四
	fmt.Printf("%s%s \n", s, s1)
	// fmt.Sprintf 可以将拼接后的值返回给变量
	s2 := fmt.Sprintf("%s%s \n", s, s1)
	// 张三李四
	fmt.Printf("%s \n", s2)

	// 字符串分割
	s3 := "/Users/cnpeng/CnPeng/04_Demos/12_Go"
	splitS := strings.Split(s3, "/")
	// [ Users cnpeng CnPeng 04_Demos 12_Go]
	fmt.Printf("%s \n", splitS)

	// 是否包含——true
	fmt.Println(strings.Contains(s2, "张三"))

	// 前缀和后缀——true
	fmt.Println(strings.HasPrefix(s2, "张"))
	// true
	fmt.Println(strings.HasSuffix(s2, "四"))

	// 子串位置——0
	fmt.Println(strings.Index(s2, "张"))
	// 9
	fmt.Println(strings.LastIndex(s2, "四"))

	// Join 拼接——+Users+cnpeng+CnPeng+04_Demos+12_Go
	fmt.Println(strings.Join(splitS, "+"))
}

3.4.4 byte 和 rune 类型

组成每个字符串的元素叫做字符。可以通过遍历或者单个获取字符串元素获得字符。字符使用单引号包裹,如:

var a := '中'
var b := 'x'

go 语言中的字符有如下两种:

  • uint8 类型,或者叫 byte 类型,代表了 ASCII 码的一个字符。
  • rune 类型,代表一个 UTF-8 字符。一个 rune 字符由一个或多个 byte 组成。

当需要处理中文、日文或其他复合字符时,需要使用 rune 类型。rune 类型实际是一个 int32

package main

import (
	"fmt"
)

func main() {
	s := "中国"

	// 普通遍历方式得到的是 byte ,最终输出结果为:228——ä184——¸173——­229——å155——›189——½
	for i := 0; i < len(s); i++ {
		fmt.Printf("%v——%c", s[i], s[i])
	}

	fmt.Println()

	// range 遍历得到的数 rune ,最终结果为:20013——中22269——国
	for _, c := range s {
		fmt.Printf("%v——%c", c, c)
	}
	fmt.Println()
}

因为 UTF-8 编码下一个中文汉字由 3-4 个字节组成,所以我们不能简单的按照字节去遍历一个包含中文的字符串,否则就会出现上面第一个遍历中的结果。

3.4.5 修改字符串

字符串是不能直接修改的。

字符串底层是一个 byte 数组,所以可以和 []byte 类型相互转换。

修改字符串时,需要先将其转换成 []rune[]byte, 修改完成后再转换为 string。无论哪种转换都会重新分配内存,并复制字节数组。

package main

import (
	"fmt"
)

func main() {

	s1 := "big"
	byteS1 := []byte(s1)
	byteS1[0] = 'p'
	// pig
	fmt.Println(string(byteS1))

	s2 := "白萝卜"
	runeS2 := []rune(s2)
	runeS2[0] = '红'
	//红萝卜
	fmt.Println(string(runeS2))
}

3.5 类型转换和类型别名

3.5.1 类型转换

Go 语言中不允许隐式转换,所有类型转换必须显示声明,而且转换只能发生在两种相互兼容的类型之间。

package main

func main() {
	var a byte = 97
	//显示类型转换
	var b int = int(a)
	
	//隐式类型转换,报错
	// var c int = a
	
	//类型不兼容,int 不能转为 bool
	//var d bool = bool(b)
	fmt.Println(d)
}

3.5.2 类型别名

  • 为现有的类型定义别名,方便调用。关键字 type

( 在 Swift 中也有这种类型别名,特别是对函数类型定义别名很有用)

package main

import "fmt"

func main() {
	//1、为 int64 起一个类型别名为,bigint
	type bigint int64
	var x bigint = 100

	//2、同时定义多个类型别名
	type (
		myint int
		mystr string
	)

	var y myint = 11
	var z mystr = "12"

	fmt.Println(x, y, z)
	fmt.Printf("x,y,z 的类型分别为:%T , %T , %T \n ", x, y, z)
}

运行结果:

cnpeng$ go run Day1.go 
100 11 12
x,y,z 的类型分别为:main.bigint , main.myint , main.mystr 

3.6 strconv 包

Go 语言中 strconv 包实现了基本数据类型和其字符串表示的相互转换。主要有以下常用函数: Atoi()Itoa()parse 系列、format 系列、append 系列。

更多函数请查看官方文档。

3.6.1 string与int类型转换

这一组函数是我们平时编程中用的最多的。

3.6.1.1 Atoi()

Atoi() 函数用于将字符串类型的整数转换为int类型,函数签名如下。

func Atoi(s string) (i int, err error)

如果传入的字符串参数无法转换为int类型,就会返回错误。

s1 := "100"
i1, err := strconv.Atoi(s1)
if err != nil {
	fmt.Println("can't convert to int")
} else {
	fmt.Printf("type:%T value:%#v\n", i1, i1) //type:int value:100
}
3.6.1.2 Itoa()

Itoa() 函数用于将 int 类型数据转换为对应的字符串表示,具体的函数签名如下。

func Itoa(i int) string

示例代码如下:

i2 := 200
s2 := strconv.Itoa(i2)
fmt.Printf("type:%T value:%#v\n", s2, s2) //type:string value:"200"
3.6.1.3 a的典故

这是 C 语言遗留下的典故。C 语言中没有 string 类型而是用字符数组(array)表示字符串,所以 Itoa 对很多 C 系的程序员很好理解。

3.6.2 Parse系列函数

Parse 类函数用于转换字符串为给定类型的值:ParseBool()ParseFloat()ParseInt()ParseUint()

3.6.2.1 ParseBool()
func ParseBool(str string) (value bool, err error)

返回字符串表示的 bool 值。

  • 当 str 为:1,t,T,TRUE,true,True 中的一种时为真值
  • 当 str 为:0,f,F,FALSE,false,False 中的一种时为假值
  • 其他输入内容一律返回 false
fmt.Println(strconv.ParseBool("t"))
fmt.Println(strconv.ParseBool("TRUE"))
fmt.Println(strconv.ParseBool("true"))
fmt.Println(strconv.ParseBool("True"))
fmt.Println(strconv.ParseBool("0"))
fmt.Println(strconv.ParseBool("f"))
3.6.2.2 ParseInt()
func ParseInt(s string, base int, bitSize int) (i int64, err error)

返回字符串表示的整数值,接受正负号。

  • base 指定进制(2到36),如果 base 为0,则会从字符串前置判断;0x 是16进制,0 是 8 进制,否则是 10 进制;

  • bitSize 指定结果必须能无溢出赋值的整数类型,0、8、16、32、64 分别代表 int、int8、int16、int32、int64;

  • 返回的 err 是 *NumErr 类型的,如果语法有误,err.Error = ErrSyntax;如果结果超出类型范围 err.Error = ErrRange

3.6.2.3 ParseUnit()
func ParseUint(s string, base int, bitSize int) (n uint64, err error)

ParseUint 类似 ParseInt 但不接受正负号,用于无符号整型。

3.6.2.4 ParseFloat()
func ParseFloat(s string, bitSize int) (f float64, err error)

解析一个表示浮点数的字符串并返回其值。

如果 s 合乎语法规则,函数会返回最为接近 s 表示值的一个浮点数(使用 IEEE754 规范舍入)。

  • bitSize 指定了期望的接收类型,32 是 float32(返回值可以不改变精确值的赋值给float32),64 是 float64;
  • 返回值 err 是 *NumErr 类型的,语法有误的,err.Error=ErrSyntax;结果超出表示范围的,返回值 f 为 ±Inferr.Error= ErrRange
3.6.2.5 代码示例
b, err := strconv.ParseBool("true")
f, err := strconv.ParseFloat("3.1415", 64)
i, err := strconv.ParseInt("-2", 10, 64)
u, err := strconv.ParseUint("2", 10, 64)

这些函数都有两个返回值,第一个返回值是转换后的值,第二个返回值为转化失败的错误信息。

3.6.3 Format系列函数

Format 系列函数实现了将给定类型数据格式化为 string 类型数据的功能。

3.6.3.1 FormatBool()
func FormatBool(b bool) string

根据 b 的值返回 "true""false"

3.6.3.2 FormatInt()
func FormatInt(i int64, base int) string

返回 i 的 base 进制的字符串表示。base 必须在2到36之间,当 base 大于 10 时,结果中会使用小写字母 az 表示大于 10 的数字。

3.6.3.3 FormatUint()
func FormatUint(i uint64, base int) string

是 FormatInt 的无符号整数版本。

3.6.3.4 FormatFloat()
func FormatFloat(f float64, fmt byte, prec, bitSize int) string

函数将浮点数表示为字符串并返回。

  • bitSize 表示 f 的来源类型(32:float32、64:float64),会据此进行舍入。
  • fmt 表示格式:f(-ddd.dddd)、b(-ddddp±ddd,指数为二进制)、e(-d.dddde±dd,十进制指数)、E(-d.ddddE±dd,十进制指数)、g(指数很大时用e格式,否则f格式)、G(指数很大时用E格式,否则f格式)。
  • prec 控制精度(排除指数部分):feE,它表示小数点后的数字个数;对 gG,它控制总的数字个数。如果 prec 为 -1,则代表使用最少数量的、但又必需的数字来表示 f 。
3.6.3.5 代码示例
s1 := strconv.FormatBool(true)
s2 := strconv.FormatFloat(3.1415, 'E', -1, 64)
s3 := strconv.FormatInt(-2, 16)
s4 := strconv.FormatUint(2, 16)

3.6.4 其他

3.6.4.1 isPrint()
func IsPrint(r rune) bool

返回一个字符是否是可打印的,和 unicode.IsPrint 一样,r 必须是:字母(广义)数字标点符号ASCII空格

3.6.4.2 CanBackquote()
func CanBackquote(s string) bool

返回字符串 s 是否可以不被修改的表示为一个单行的、没有空格tab之外控制字符反引号字符串

3.6.4.3 其他

除上文列出的函数外,strconv 包中还有 Append系列、Quote系列等函数。具体用法可查看官方文档。

更多函数请查看官方文档。

更多推荐

七夕特别篇 | 浪漫的Bug

文章目录前言一、迷失的爱情漩涡(多线程中的错误同步)1.1Bug背景1.2Bug分析1.3Bug解决二、心形积分之恋(心形面积计算中的数值积分误差)1.1Bug背景1.1.1背景1.1.2数学模型1.2Bug分析1.2.1初始代码1.2.2代码工作流程图1.2.3代码分析1.3Bug解决三、总结Bug1:多线程环境中的

【已解决】matrix contains invalid numeric entries,记录bug修改

文章目录摘要原因解决办法图像分类网络AlexNetVGGNetGooLeNet系列ResNetDenseNetSwinTransformerMAECoAtNetConvNeXtV1、V2MobileNet系列MPViTVITSWAEfficientNet系列MOBILEVITEdgeViTsMixConvRepLKNe

绘图系统四:定制绘图风格

文章目录创建控件绘图风格可定制绘图风格的绘图系统代码组织📈一三维绘图系统📈二多图绘制系统📈三坐标轴定制源码地址Python打造动态绘图系统创建控件尽管从matplotlib的角度来说,绘图风格也算是图像类型的一部分,但诸如点线字体标题等内容太过复杂,为了减轻DrawType的负担,所以新建一个组件。有了DrawT

R语言RSTAN MCMC:NUTS采样算法用LASSO 构建贝叶斯线性回归模型分析职业声望数据...

全文链接:http://tecdat.cn/?p=24456如果你正在进行统计分析:想要加一些先验信息,最终你想要的是预测。所以你决定使用贝叶斯(点击文末“阅读原文”获取完整代码数据)。相关视频但是,你没有共轭先验。你可能会花费很长时间编写Metropolis-Hastings代码,优化接受率和提议分布,或者你可以使用

【医学影像数据处理】 Dicom 文件格式处理汇总

在医学影像的数据存储领域,是存在一定的行业标准的。X光、CT机器等等医疗器械等生产企业,会依据行业标准,对采集的数据进行规范化的存储。这里面就包括了大名鼎鼎的DICOM3.0协议,上述的摄影形式大部分也都是以这种形式进行存储和传播的。但是呢,在医学领域进行数据处理的时候,经常会遇到除DICOM外其他的数据形式,比如常见

gateway之断言的使用详解

文章目录gateway产生的背景,为什么要是用gateway什么是网关gateway带来的好处功能特征gateway在项目中使用的依赖什么是断言断言分类内置自定义示例断言和过滤器的不同gateway产生的背景,为什么要是用gateway一个系统会被拆分为多个微服务,作为客户端要如何去调用这么多的微服务?如果没有网关的存

使用 Amazon EC2 预留实例最大限度地节省成本和提高灵活性

简介:随着云计算不断改变企业的运营方式,优化成本已成为首要任务。利用AmazonEC2预留实例是实现云端成本节约最有效的方法之一。本文将探讨什么是AmazonEC2预留实例,它与按需实例的区别,以及它在成本节约和灵活性方面提供的好处。背景:云计算改变了IT格局,使企业能够按需扩展基础设施,仅为所消耗的资源付费。但是,随

短视频矩阵系统源代码开发搭建分享--代码开源SaaS

一、什么是短视频矩阵系统?短视频矩阵系统是专门为企业号商家、普通号商家提供帐号运营从流量到转化成交的一站式服务方案,具体包含:点赞关注评论主动私信,评论区回复,自动潜客户挖掘,矩阵号营销,自动化营销,粉丝管理等功能,可以帮助企业或商家快速批量制作高质量短视频,扩大企业宣传,提升企业经营效果。通过短视频矩阵系统的运营,可

React面试题总结(一)

1、redux本来是同步的,为什么它能执行异步代码?实现原理是什么?中间件的实现原理是什么?1、Redux-thunk这个中间件支持异步操作2、执行异步的操作首先需要下载一个thunk,通过thunk来进行异步的一个操作,支持异步操作,可以使用dispatch和getState来进行数据的获取或状态3、Redux是一个

【C++】STL—— unordered_map的介绍和使用、 unordered_map的构造函数和迭代器、 unordered_map的增删查改函数

文章目录1.unordered_map的介绍2.unordered_map的使用2.1unordered_map的构造函数2.2unordered_map的迭代器2.3unordered_map的容量和访问函数2.4unordered_map的增删查改函数1.unordered_map的介绍unordered_map的

【Java 基础篇】Java多线程编程详解:线程创建、同步、线程池与性能优化

Java是一门强大的编程语言,其中最引人注目的特性之一是多线程支持。多线程允许我们在同一程序中同时执行多个任务,这大大提高了应用程序的性能和响应能力。本文将深入介绍Java线程的基础知识,无论您是初学者还是有一些经验的开发人员,都将从中获益。什么是线程?在计算机科学领域,线程是指在一个进程内部执行的独立单元。一个进程可

热文推荐