天天看点

【Go从学会到学废】(五) 数据类型数据类型基本类型高级类型

数据类型

类型确定一组值以及特定于这些值的操作和方法。类型可以由类型名称(如果它有的话)表示,或者使用类型文字(由现有类型组成类型)指定。

  • 基本类型:
    • 整型
    • 浮点型
    • 布尔型
    • 字符串
  • 高级类型:
    • 数组
    • 切片
    • 结构体
    • 函数
    • map (映射或者说字典)
    • channel(通道)
    • 接口

基本类型

布尔类型

布尔类型表示一组布尔真值,由预先声明的常量真和假表示。预先声明的布尔类型是bool;它是一个已定义的类型。

true
false
           

数值类型

数值类型表示一组整数或浮点值。预先声明的与体系结构无关的数值类型有:

uint8       the set of all unsigned  8-bit integers (0 to 255)
uint16      the set of all unsigned 16-bit integers (0 to 65535)
uint32      the set of all unsigned 32-bit integers (0 to 4294967295)
uint64      the set of all unsigned 64-bit integers (0 to 18446744073709551615)

int8        the set of all signed  8-bit integers (-128 to 127)
int16       the set of all signed 16-bit integers (-32768 to 32767)
int32       the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64       the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)

float32     the set of all IEEE-754 32-bit floating-point numbers
float64     the set of all IEEE-754 64-bit floating-point numbers
//复数
complex64   the set of all complex numbers with float32 real and imaginary parts
complex128  the set of all complex numbers with float64 real and imaginary parts

byte        alias for uint8
rune        alias for int32
           
  • byte

    等同于

    int8

    ,常用来处理

    ascii

    字符
  • rune

    等同于

    int32

    ,常用来处理

    unicode

    utf-8

    字符(作用类似于

    byte

  • byte

    就是类似于

    C/C++

    里面的字节

n位整数的值是n位宽,用2的补数表示。

还有一组预先声明的数字类型,具有特定于实现的大小:

uint     either 32 or 64 bits //电脑是32位就是  uint32, 电脑是64位就是   uint64
int      same size as uint //
uintptr  an unsigned integer large enough to store the uninterpreted bits of a pointer value  //一个大到无法解释的无符号整形,无穷大
           

字符串类型

字符串类型表示一组字符串值。字符串值是一个(可能是空的)字节序列。字节数称为字符串的长度,并且永远不会为负。字符串是不可变的:一旦创建,就不可能改变字符串的内容。预先声明的字符串类型为

string

;它是一个已定义的类型。

可以使用内置函数

len

来查找字符串

s

的长度。如果字符串是常量,则长度是编译时常量。字符串的字节可以通过整数索引

len(s)-1

访问。获取该元素的地址是非法的;如果

s[i]

是一个字符串的第i字节,

&s[i]

是无效的。

高级类型

数组类型

数组是单个类型(称为元素类型)的元素的编号序列。元素的数量称为数组的长度,并且永远不会为负。

长度是数组类型的一部分;它必须计算为一个非负的常数,可以用

int

类型的值表示。数组a的长度可以用内置函数

len

来计算。元素可以通过整数索引

len(a)-1

来寻址。数组类型总是一维的,但可以组合成多维类型。

[32]byte    //字节数组
[2*N] struct { x, y int32 }   //结构体数组
[1000]*float64
[3][5]int    //二维数组
[2][2][2]float64  // same as [2]([2]([2]float64))
           

切片类型

slice

是底层数组的连续段的描述符,提供对该数组中元素的编号序列的访问。片类型表示其元素类型的数组的所有片的集合。元素的数量被称为片的长度,并且永不为负。未初始化的片的值是

nil

  1. 切片

    s

    的长度可以通过内置函数

    len

    来发现;与数组不同,它可能在执行过程中改变。元素可以通过整数索引 到

    len(s)-1

    来寻址。给定元素的片索引可能小于底层数组中相同元素的索引。
  2. 切片一旦初始化,就总是与保存其元素的底层数组相关联。因此,一个片与其数组以及同一数组的其他片共享存储空间;相反,不同的数组总是表示不同的存储。
  3. 切片的底层数组可以扩展到片的末尾。容量就是这个范围的度量:它是切片的长度和切片以外的数组长度的总和;通过从原来的切片中切出一个新的切片,可以创建一个长度到那个容量的切片。切片a的容量可以使用内置函数

    cap(a)

    来发现。
  4. 使用内置函数

    make

    为给定元素类型T创建一个新的初始化的片值,该函数接受片类型和指定长度和可选容量的参数。使用

    make

    创建的片总是分配一个新的隐藏数组,返回的片值将指向该数组。也就是说,执行
make([]T, length, capacity)
make([]int, 50, 100)
new([100]int)[0:50]
           
  • 与数组一样,切片总是一维的,但可以组合成更高维的对象。
  • 对于数组而言,内部数组的构造总是相同的长度;
  • 但是对于切片,内部长度可以动态变化。此外,切片内部必须单独初始化。
  • 切片在函数间的传输就是传输的指针,所以对于切片的修改,会导致切片底层的数据进行修改。
  • 数组在函数间的传输默认的是值传输,所以对于数组的修改,不会导致源数据的修改,因此想要修改源数据内容,需要传输到函数的是数组的地址,这样就可以改变指针所指向的具体内容。

总的来说:

  • 切片是指针类型,数组是值类型
  • 数组的长度是固定的,而切片不是(切片是动态的数组)
  • 切片比数组多一个属性:容量(cap)
  • 切片的底层是数组

结构体类型

结构是一个名为字段的命名元素序列,每个字段都有一个名称和一个类型。字段名可以显式指定(IdentifierList),也可以隐式指定(EmbeddedField)。在结构中,非空白字段名必须是唯一的。

// A struct with four embedded fields of types T1, *T2, P.T3 and *P.T4
struct {
	T1        // field name is T1
	*T2       // field name is T2
	P.T3      // field name is T3
	*P.T4     // field name is T4
	x, y int  // field names are x and y
}
//这是错的,  *T和 *p.T,T重复
struct {
	T     // conflicts with embedded field *T and *P.T
	*T    // conflicts with embedded field T and *P.T
	*P.T  // conflicts with embedded field T and *T
}
//可以在后面接字符串作为标签,后面json会用到
struct {
	x, y float64 ""  // an empty tag string is like an absent tag
	name string  "any string is permitted as a tag"
	_    [4]byte "ceci n'est pas un champ de structure"
}

// A struct corresponding to a TimeStamp protocol buffer.
// The tag strings define the protocol buffer field numbers;
// they follow the convention outlined by the reflect package.
struct {
	microsec  uint64 `protobuf:"1"`
	serverIP6 uint64 `protobuf:"2"`
}
           

指针类型

指针类型表示指向给定类型(称为指针的基类型)变量的所有指针的集合。未初始化指针的值为

nil

*Point
*[4]int
           

函数类型

函数类型表示具有相同参数和结果类型的所有函数的集合。函数类型的未初始化变量的值为

nil

func()
func(x int) int
func(a, _ int, z float32) bool
func(a, b int, z float32) (bool)
func(prefix string, values ...int)
func(a, b int, z float64, opt ...interface{}) (success bool)
func(int, int, float64) (float64, *[]int)
func(n int) func(p *T)
           

在参数或结果列表中,名称(IdentifierList)要么全部存在,要么全部不存在。如果存在,则每个名称代表指定类型的一个项(参数或结果),签名中的所有非空白名称必须是惟一的。如果没有,每个类型代表该类型的一个项。参数和结果列表总是带括号的,但如果只有一个未命名的结果,则可以将其写成无括号类型。

函数签名中的最后一个传入参数可能有一个前缀为…的类型。具有这种参数的函数称为variadic,可以在调用该参数时使用零个或多个参数。(可变参数)

接口类型

接口类型指定称为其接口的方法集合。接口类型的变量可以存储具有接口的任何超集的方法集的任何类型的值。这样的类型被称为实现接口。接口类型的未初始化变量的值为

nil

interface {
	Read([]byte) (int, error)
	Write([]byte) (int, error)
	Close() error
}
           

显式指定的每个方法的名称必须是唯一的,不能为空。

interface {
	String() string
	String() string  // illegal: String not unique,字符串不唯一
	_(x int)         // illegal: method must have non-blank name,不能为空
}
           

字典类型/映射类型(map)

map

是一种称为元素类型的无序元素组,由称为键类型的一组惟一键索引。未初始化映射的值是

nil

对于键类型的操作数,必须完全定义比较运算符

==

!=

;因此,键类型不能是函数、map或切片。如果键类型是接口类型,则必须为动态键值定义这些比较运算符;失败将导致运行时错误。

map[string]int
map[*T]struct{ x, y float64 }
map[string]interface{}
           

映射元素的数量称为它的长度。对于

map m

,可以使用内置函数

len

来发现它,并且在执行过程中可能会发生变化。元素可以在执行期间使用赋值和检索与索引表达式添加;它们可以通过内置的删除功能被删除。

使用内置函数

make

创建一个新的空映射值,该函数将映射类型和可选的容量提示作为参数:

make(map[string]int)
make(map[string]int, 100)
           

初始容量不限制其大小:映射会增长以容纳存储在其中的项的数量,

nil

映射除外。一个空映射等价于一个空映射,除了没有元素可以被添加。

通道类型

通道为并发执行函数提供了一种机制,通过发送和接收指定元素类型的值进行通信。未初始化通道的值为

nil

(专门为了Go并发做的)

可选的

<-

操作符指定通道方向、发送或接收。如果没有给出方向,则信道是双向的。通过分配或显式转换,可以将信道限制为仅发送或仅接收。

chan T          // can be used to send and receive values of type T
chan<- float64  // can only be used to send float64s    发送
<-chan int      // can only be used to receive ints     接收
           

<-

操作符与最左边的

chan

可以相关联:

chan<- chan int    // same as chan<- (chan int)
chan<- <-chan int  // same as chan<- (<-chan int)
<-chan <-chan int  // same as <-chan (<-chan int)
chan (<-chan int)

make(chan int, 100)