golang数据类型

一、数据类型分为:

  1. 布尔型
    布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。
  2. 数字类型
    整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。
  3. 字符串类型:
    字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
  4. 派生类型:
    包括:
    (a) 指针类型(Pointer)
    (b) 数组类型
    © 结构化类型(struct)
    (d) Channel 类型
    (e) 函数类型
    (f) 切片类型
    (g) 接口类型(interface)
    (h) Map 类型

1 数字类型分为:
Go 也有基于架构的类型,例如:int、uint 和 uintptr。

  1. uint8
    无符号 8 位整型 (0 到 255)
  2. uint16
    无符号 16 位整型 (0 到 65535)
  3. uint32
    无符号 32 位整型 (0 到 4294967295)
  4. uint64
    无符号 64 位整型 (0 到 18446744073709551615)
  5. int8
    有符号 8 位整型 (-128 到 127)
  6. int16
    有符号 16 位整型 (-32768 到 32767)
  7. int32
    有符号 32 位整型 (-2147483648 到 2147483647)
  8. int64
    有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)

2 浮点类型:

  1. float32
    IEEE-754 32位浮点型数
  2. float64
    IEEE-754 64位浮点型数
  3. complex64
    32 位实数和虚数
  4. complex128
    64 位实数和虚数

3 其他数字类型:

  1. byte
    类似 uint8
  2. rune
    类似 int32
  3. uint
    32 或 64 位
  4. int
    与 uint 一样大小
  5. uintptr
    无符号整型,用于存放一个指针

二、基本数据类型
1、变量和常量
普通赋值:
// var 变量名称 变量类型 = 值
var num int = 1
平行赋值
var num1,num2 int = 1, 2
多行赋值
var (
num1 int = 1
num2 int = 2
)
2、整数类型的命名和宽度
Go的整数类型一共有10个
其中计算架构相关的整数类型有两个: 有符号的整数类型 int, 无符号的整数类型 uint。
在不同计算架构的计算机上,它们体现的宽度(存储某个类型的值所需要的空间)是不一样的。空间的单位可以是bit也可以是字节byte。

3、整数类型值的表示法
如果以8进制为变量num赋值:

num = 039 // 用"0"作为前缀以表明这是8进制表示法

如果以16进制为变量num赋值:

num = 0x39

4、浮点数类型
浮点数类型有两个:float32/float64 浮点数类型的值一般由整数部分、小数点"."和小数部分组成。另外一种表示方法是在其中加入指数部分。指数部分由"E"或"e"以及带正负号的10进制整数表示。例:3.9E-2表示浮点数0.039。3.9E+1表示浮点数39。
有时候浮点数类型值也可以被简化。比如39.0可以被简化为39。0.039可以被简化为.039。 在Go中浮点数的相关部分只能由10进制表示法表示。

5、复数类型
复数类型有两个:complex64和complex128。实际上,complex64类型的值会由两个float32类型的值分别表示复数的实数部分和虚数部分。而complex128类型的值会由两个float64类型的值表示复数的实数部分和虚数部分。
负数类型的值一般由浮点数表示的实数部分、加号"+"、浮点数表示的虚数部分以及小写字母"i"组成,比如3.9E+1 + 9.99E-2i。

6、byte与rune
byte与rune都属于别名类型。byte是uint8的别名类型,而rune是int32的别名类型。
一个rune的类型值即可表示一个Unicode字符。一个Unicode代码点通常由"U+“和一个以十六进制表示法表示的整数表示,例如英文字母’A’的Unicode代码点为"U+0041”。

7、字符串类型
字符串的表示法有两种,即:原生表示法和解释型表示法。原生表示法,需用用反引号"`“把字符序列包起来,如果用解释型表示法,则需要用双引号”""包裹字符序列。

var str1 string = "str"
var str1 string = `str`

二者的区别是,前者表示的是所见即所得的(除了回车符)。后者所表示的值中转义符会起作用。字符串值是不可变的,如果我们创建了一个此类型的值,就不可能再对它本身做任何修改。

三、高级数据类型
1、数组类型
一个数组是可以容纳若干相同类型的元素的容器。数组的长度是固定的。如下声明一个数组类型:

type MyNumbers [3]int

类型声明语句由关键字type、类型名称和类型字面量组成
上面这条类型声明语句实际上是为数组类型[3]int声明了一个别名类型。这使得我们可以把MyNumbers当作数组类型[3]int来使用。
我们表示这样一个数组类型的值的时候。应该把该类型的类型字面量写在最左边,然后用花括号包裹该值包含的若干元素,各元素之间以(英文半角)逗号分割,即:

[3]int{1,2,3}

现在我们把这个数组字面量赋给一个名为numbers的变量:

var numbers = [3]int{1,2,3}

这是一条变量声明语句,它在声明变量的同时为该变量赋值
另一种方式是在其中的类型字面量中省略代表其长度的数组,例:

var numbers = [...]int{1,2,3}

可以用如下方式访问该变量中的任何一个元素。例:

numbers[0]
numbers[1]
numbers[2]

如果要修改数组值中的某一个元素值,可以:

numbers[1] = 4

可以用如下方式获取数组长度:

var length = len(numbers)

如果一个数组没有赋值,则它的默认值为[length]type{0,0,0…}

2、切片类型
(1) 基础
切片(slice)与数组一样也是可以若干相同类型元素的容器。与数组不同的是切片类型的长度不确定。每个切片值都会将数组作为其底层数据结构。表示切片类型的字面量如:

[]int

或者是:

[]string

切片类型的声明可以这样:

type MySlice []int

对切片值的表示也与数组值相似

[]int{1,2,3}

操作数组值的方法同样适用于切片值。还有一种操作数组的方式叫做“切片”,实施切片操作的方式就是切片表达式。例:

var number3 = [5]int{1,2,3,4,5}
var slice1 = numbers3[1:4]

上例中切片表达式numbers3[1:4]的结果为[]int{2,3,4}很明显被切下的部分不包含元素上界索引指向的元素。实际上slice1这个切片值的底层数组正是number3的值。
我们也可以在切片值上实施切片操作:

var slice2 = slice1[1:3]

除了长度切片值以及数组值还有另外一个属性–容量。数组的容量总是等于其长度,而切片值的容量往往与其长度不同

var capacity2 int = cap(slice2)

切片类型属于引用类型,它的零值即为nil,即空值。如果我们只声明了一个切片类型而不为它赋值,则它的默认值:nil。

(2) 切片的更多操作方法
有些时候我们可以在方括号中放入第三个正整数

numbers3[1:4:4]

第三个正整数为容量上界索引,它意义在于可以把作为结果的切片值的容量设置的更小。它可以限
我们通过这个切片值对其底层数组中的更多元素的访问。上节中numbers3和slice的赋值语句如下:

var numbers3 = [5]int{1,2,3,4,5}
var slice1 = numbers3[1:4]

这时,变量slice1的值是[]int{2,3,4}。但是我们可以通过如下操作将其长度延展与其容量相同:

slice1 = slice1[:cap(slice1)]

通过此操作,变量slice1的值变为了[]int{2,3,4,5},且其长度和容量均为4。现在number3的值中的索引值在(1,5)范围内的元素都被体现在了slice1的值中。这是以number3的值是slice1的值的底层数组为前提的。这意味着我们可以轻而易举地通过切片访问其底层数组中对应索引值更大的更多元素。如果我们编写的函数返回了这样一个切片值,那么得到它的程序很可能会通过这种技巧访问到本不应该暴露给它的元素。
如果我们在切片中加入了第三个索引(即容量上限索引),如:

var slice1 = numbers3[1:4:4]

那么在此之后,我们将无法通过slice1访问到number3的值中的第五个元素。
虽然切片值在上述方面受到了其容量的限制。但是我们可以通过另外一种手段对其进行不受限制的扩展。这需要用到内建函数append。append会对切片值进行扩展并返回一个新的切片值,使用方法如下:

slice1 = append(slice1, 6, 7)

通过上述操作,slice1的值变为了[]int{2,3,4,6,7}。一旦扩展操作超出了被操作的切片值的容量,那么该切片的底层数组就会被替换 最后一种操作切片的方式是“复制”。该操作的实施方法是调用copy函数。该函数接收两个类型相同的切片值作为参数,并把第二个参数值中的元素复制到第一个参数值中的相应位置(索引值相同)上。这里有两点需要注意:

这种复制遵循最小复制原则,即:被复制的元素的个数总是等于长度较短的那个参值的长度。
与append函数不同,copy函数会直接对其第一个参数值进行修改。
例:

var slice4 = []int{0,0,0,0,0,0}
copy(slice4, slice1)

通过上述复制操作,slice4会变成[]int{2,3,4,6,7,0,0}。

3、字典类型
Go语言的字典(Map)类型是一个哈希表的实现。字典类型的字面量如下:

map[K]T

其中,"K"为键的类型,而"T"则代表元素(值)的类型。如果我们描述一个键类型为int,值类型为string的字典类型的话:

map[int]string

字典的键类型必须是可比较的,否则会引起错误,即键不能是切片、字典、函数类型
字典值的字面量表示法实际上与数组的切片的字面量表示法很相似。最左边仍然是类型字面量,右边紧挨着由花括号包裹且有英文逗号分隔的键值对。每个键值对的键和值之间由冒号分隔。以字典类型map[int]string为例。他的值的字面量可以是这样的:

map[int]string{1:"a",2:"b"m,3:"c"}

我们可以把这个值赋给一个变量

mm := map[int]string{1:"a",2:"b",3:"c"}

可用索引表达式取出字典中的值:

b := mm[2]

可以用索引表达式赋值:

mm[2] = b + "2"

这样mm中键为2的值变为了"b2"。可以用如下方式向字典中添加一个键值对:

mm[4] = ""

对于字典值来说,如果指定键没有对应的值则默认为该类型的空值。所以mm[5]会返回一个""。但是这样的话我们就不知道mm[5]到底是""还是mm[5]没有这个值。所以go提供了另外一种写法:

e, ok := mm[5]

针对字典的索引表达式可以有两个求职结果,第二个求职结果是bool类型的。它用于表明字典值中是否存在指定的键值对。 从字典中删除键值对的方法非常简单,仅仅是调用内建函数delete:

delete(mm, 4)

无论mm中是否存在以4为键的键值对,delete都删除。 字典类型属于引用类型,它的零值即为nil

4、通道类型
通道(Channel)是Go语言中一种非常独特的数据结构。它可用于在不同Goroutine之间传递类型化的数据。并且是并发安全的。相比之下,之前几种数据类型都不是并发安全的。
Goroutine可以被看作是承载可被并发执行的代码块的载体。它们由Go语言的运行时系统调度,并依托操作系统线程(又称内核线程)来并发地执行其中的代码块。
通道类型的表示方法很简单,仅由两部分组成:

chan T

在这个类型字面量中,左边是代表通道类型的关键字chan,而右边则是一个可变的部分,即代表该通道类型允许传递的数据的类型(或称通道的元素类型)。
与其他的数据类型不同,我们无法表示一个通道类型的值,因此,我们无法用字面量来为通道类型的变量赋值。只能通过调用内建函数make来达到目的。make参数可接受两个参数,第一个参数是代表了将被初始化的值的类型的字面量(例: chan int),而第二个参数则是值的长度,例如,若我们想要初始化一个长度为5且元素类型为int的通道值,则需要这样写:

make(chan int, 5)

make函数也可以被用来初始化切片类型或字典类型的值。
暂存在通道值中的数据是先进先出。下面,我们声明一个通道类型的变量,并为其赋值:

ch1 := make(chan string, 5)

这样一来,我们就可以使用接受操作符<-向通道值发送数据了。当然,也可以使用它从通道值接收数据,例如,如果我们要向通道ch1 发送字符串"value1",那么应该这样做:

ch1 <- "value1"

如果我们从ch1那里接收字符串,则要这样:

<- ch1

我们可以把接受到字符串赋给一个变量,如:

value := <- ch1

与针对字典值的索引表达式一样,针对通道值的接受操作也可以有第二个结果值:

value, ok := <- ch1

这里的ok的值是bool类型的。它代表了通道值的状态,true代表通道值有效,而false则代表通道值已无效(或称已关闭),更深层次的原因是,如果在接受操作进行之前或过程中通道值被关闭了,则接收操作会立即结束并返回一个该通道值的元素类型的零值。
可以通过函数close来关闭通道:

close(ch1)

对通道值的重复关闭会引发运行时异常,会使程序崩溃。在通道值有效的前提下,针对它的发送操作会在通道值已满(其中缓存的数据的个数已等于它的长度)时被阻塞。而向一个已被关闭的通道值发送数据会引发运行时异常。针对有效通道值的接收操作会在它已经为空时被阻塞。通道类型属于引用类型,它的零值为nil。

5、通道的更多种类
上一节中的通道实际上只是Go中的通道的一种。是带缓冲的通道,或者简称为缓冲通道。
通道有缓冲和非缓冲之分,缓冲通道中可以缓存N个数据,我们在初始化一个通道值的时候必须指定这个N,**相对的非缓冲通道不会缓存任何数据,发送方在向通道发送数据的时候会立即被阻塞。直到有一个接收方已从该通道中接收了这条数据。**非缓冲的通道值的初始化方法如下:

make(chan int, 0)

除了上述分类方法,我们还可以以数据在通道中的传输方向为依据来划分通道。默认情况下,通道都是双向的,即双向通信。如果数据只能在通道中单向传输,那么该通道被称作单向通道。我们在初始化一个通道值的时候不能指定为单向。但是在编写类型声明的时候可以:

type Receiver <- chan int

类型Receiver代表了一个只从中接收数据的单向通道类型,这样的通道也被称为接收通道。在关键字chan左边的接收操作符<-表示了数据的流向。相对应的,如果我们想声明一个发送通道类型,那么应该这样:

type Sender char <- int

这次<-被放在了chan的右边,并且“箭头”直指“通道”。我们可以把一个双向通道赋予上述类型的变量,就像这样:

var myChannel = make(chan int, 3)
var sender Sender = myChannel
var receiver Receiver = myChannel

但是反过来是不行的:

var myChannel1 chan int = sender

单向通道的作用主要是约束程序对通道值的使用方式,比如,我们调用一函数时给予它一个发送通道作为参数,以此来约束它只能向该通道发送数据。又比如,一个函数将一个接受通道作为结果返回,以此来约束调用该函数的代码只能从这个通道中接收数据。

### Golang 数据类型概述 在 Go 语言中,支持多种内置的数据类型。这些数据类型分为基本类型和复合类型。 #### 基本数据类型 Go 支持以下几种基本数据类型[^3]: - **布尔类型 (`bool`)** 表示真或假的逻辑值。 - **数值类型** - 整形: - `int8`, `int16`, `int32`, `int64`: 有符号整数 - `uint8`, `uint16`, `uint32`, `uint64`: 无符号整数 - `byte`: 同义于 `uint8` - `rune`: 同义于 `int32`,用于表示 Unicode 码点 - `int`, `uint`: 平台相关的默认整型大小 - 浮点型: - `float32`, `float64` - 复杂浮点型: - `complex64`, `complex128` - **字符串 (`string`)** 字符串是一组不可变字符序列,由双引号包围。 #### 查看变量的字节大小和数据类型 为了获取变量的具体信息,在程序运行期间可以通过特定函数来实现这一点。例如,要打印出一个变量的实际占用空间以及其具体类型,可以使用如下方式[^4]: ```go package main import ( "fmt" "unsafe" ) func main() { var i int = 100 fmt.Printf("i 的类型:%T\n", i) fmt.Printf("i 占用的空间大小:%d bytes\n", unsafe.Sizeof(i)) } ``` 这段代码展示了如何利用标准库中的 `fmt` 包来进行格式化输出,并借助 `unsafe.Sizeof()` 函数计算给定表达式的存储需求。 #### 显式类型转换 值得注意的是,在 Go 中不同类型之间的赋值操作不会发生隐含的自动转型;相反地,程序员必须通过显示的方式完成这一过程。对于简单的数值类型间转化,遵循这样的模式[^5]: ```go var a uint8 = 255 var b int = int(a) // 将 uint8 转换为 int 类型 ``` 这种设计有助于减少潜在错误并提高代码的安全性和可读性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值