美文网首页
五、复杂类型

五、复杂类型

作者: UUID | 来源:发表于2018-04-23 18:46 被阅读8次

在第三节我们简单的介绍了下数值类型、字符串类型和基本操作。现在介绍一下golang内置的稍微复杂点的类型:数组和映射(map)以及自定义类型及其操作。

1、数组

数组和字符串一样,是使用连续的内存空间进行存储,而且都是不可变的。不可变是什么意思呢,就是存储数据的地址空间是不会改变的,对于字符串来说,字符串任何字符都不能被改变,对于数组来说,并不是说数组内容不能改变。而且因为使用连续的地址空间,所以存取的时间复杂度为o(1)。
声明和定义数组方法如下:

var typeArray [N]Type

这样我们就申明了一个类型为任意存在的类型Type,大小为N的数组变量typeArray。比如:

#容量为10的int类型数组
var intArray [10]int

#容量为10的string类型数组
var strArray [10]string

定义好后,编译器会自动给它们设置对应的零值,对于数值类型,就是对应的0,对于字符串类型,就是空字符串“”,对于bool类型,就是false。数组通过[]+下下标的方式访问,下标从0开始。验证一下:

intArray[0] = 10
fmt.Println(intArray) //[10 0 0 0 0 0 0 0 0 0]

当然,我们可以申明和初始化一起做

var intArray = [3]int{1,2,3} // intArray := [3]int{1,2,3}

如果申明和初始化一起做,也可以不用指定大小,比如复制了一个个数未知的字符串,我们不会要一个个数吧?那也太麻烦了。对于这种情况,用...代替,表明自动计算大小。

var intArray = [...]int{1,2,3,4,5,6.........}

当然,数组里面也可以保存数组,这样就可以组成二维或者多维数组了,比如一个二维数组:

var array [2][2]int
array[0][0] = 10
fmt.Println(array) //[[10 0] [0 0]]

数组在定义的时候,就需要指定容量大小。但有的时候,我们一开始并不知道具体需要多大的大小,如果小了,剩余的数据没地方存,如果太大了,内存空间利用率又太低。尤其是在云时代,任何的存储和带宽都需要成本。就没有其他语言中的动态增长的数组吗?go这么强大,当然也提供了,那就是slice(切片)。

2、slice 切片

看看slice如何申明:

var intSlice []int

仔细一看,申明其实就是少了数组的大小而已。再看看如何在申明时初始化:

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

有没有感觉,还是一样的,只是少了数组的大小。其实,切片是数组的一个片段,本身不保存数据,是数组片段的一个引用。那么如何从数组得到一个切片呢?看下面:

var intArray = [5]int{1,2,3,4,5}
var intSlice = intArray[1:3]
fmt.Println(intSlice) // [2 3]

对数组使用[from:to]就能得到数组从[from,to)的一个片段引用(切片),如果是从from到数组最后一个元素,我们可以省略to

var intArray = [5]int{1,2,3,4,5}
var intSlice = intArray[1:]
fmt.Println(intSlice) // [2 3 4 5]

如果是从0,到to,我们可以省略from

var intArray = [5]int{1,2,3,4,5}
var intSlice = intArray[:3]
fmt.Println(intSlice) // [1 2 3]

如果from和to都省略的话,就是整个数组的切片,所以切片不可能比底层数组的容量还大。对切片的修改,就是对底层数组的修改:

var intArray = [5]int{1,2,3,4,5}
var intSlice = intArray[1:3]
intSlice[0] = 0
fmt.Println(intArray) //[1 0 3 4 5]
fmt.Println(intSlice) // [0 3]

既然切片不能超过底层数组的容量,那么,如何实现动态增长呢?通过内置函数 append就可以实现,当容量不够的时候,就会申请一个容量更大的新数组,然后把老数组的数据拷贝过去,然后销毁老数组。其实动态增长的数组实现方式都是一样,只不过是增长因子可能不同而已。

var intSlice = []int{1,2,3}
intSlice = append(intSlice,[]int{4,5,6}...)
fmt.Println(intSlice) // [1 2 3 4 5 6]

如果一个方法需要的是一个切片,但是我们只有一个数组,如何传进去呢?我们在传入数组参数后面加...就可以了。

3、 map 映射

映射是一个键值对,通过键值能获取到对应的值,就是值映射到一个键上。在其他语言中,可能叫做map,可能叫做字典,其实是一样的都是键值对。只不过比起java来说类型有点少,只有hashMap。看下定义和初始化方式:

//var name map[keyType] valueType
var dic map[string] string
dic = make(map[string] string)
dic["name"]="Jin"
dic["app"]="Golang"
fmt.Println(dic) //map[app:Golang name:Jin]
fmt.Println(dic["name"]) // "Jin"

map的初始化只能通过内置函数make初始化,返回的是指向map的指针
使用map需要注意的几点:
map是无序的
map的长度不固定(可用内置函数len()查看map包含键值对的个数)
map只能通过key值进行操作
map是线程不安全的

使用内置函数delete()删除一个键值对

delete(dic,"name")
fmt.Println(dic) // map[app:Golang]

4、自定义类型

除了之前说过的类型,我们还可以自定义类型。格式为 type typeName typeType
比如,int类型其实是uint32的别名,看看如何定义的:

type int uint32

我们也可以定义一个其他类型的别名

type jin int64

对于这样的定义,其实意义不是很大,我们可以定义更复杂的类型

type user struct {
  name string
  age uin8
}

我们定义了一个user类型,它有两个属性:name和age
如何初始化(实例化)呢?

var xiaoMing = user{name:"xiaoMing",age:12}

这样我们就初始化了一个user对象--xiaoMing。我们也可以用内置函数new来创建自定义对象

var xiaoMing = new(user)
user.name = "xiaoMing"
user.age = uint8(12)

属性分别为xiaoMing和12
如果我们按照定义的顺序设置属性的话,可以把属性名去掉:

var xiaoMing = user{"xiaoMing",12}

如果只是设置部分属性,或者设置的顺序不是定义的顺序,就会导致问题,所以建议都把属性名加上,这样很直观,而且便于维护。

好了,我们可以自定义类型了,但是如何操作这些类型的实例呢。请看下节,函数和方法。

相关文章

  • 五、复杂类型

    在第三节我们简单的介绍了下数值类型、字符串类型和基本操作。现在介绍一下golang内置的稍微复杂点的类型:数组和映...

  • 第二天半卒

    数据类型分为两种:简单类型和复杂类型; 简单类型包括五种,分别是:undefined 未定义类型 ...

  • ES6新增的数据类型

    Symbol 类型(基本) Set 类型(复杂) Map 类型(复杂) WeakSet 类型(复杂) WeakMa...

  • Hive常用函数总结

    目录:一、关系运算二、数学运算三、逻辑运算四、复杂的数据类型 array、map、struct五、复杂类型访问操作...

  • 时间对象、引用类型

    问题 基础类型有哪些?复杂类型有哪些?有什么特征? 五种简单数据类型UndefinedNullBooleanNum...

  • web前端ES6/7/8新特性

    ES6中新增了哪些数据类型?Symbol类型(基本)Set类型(复杂)Map类型(复杂)WeakSet类型(复杂)...

  • 2019-12-24 从零开始的JS学习 三

    内置对象Date 数组对象 字符串对象 简单类型和复杂类型 五大数据类型基本数据类型:string number ...

  • js学习笔记记录

    基本数据类型(五种)与复杂数据类型(对象)typeof判断数据类型(数字、字符串、布尔、undefined、函数)...

  • 时间对象、引用类型

    1.基础类型有哪些?复杂类型有哪些?有什么特征? 基础数据类型:指的是简单的数据段 在JavaScript中有五种...

  • JavaScript 学习笔记

    五种基本数据类型和一种复杂数据类型 最基础的语法: 基本操作符: 控制语句 函数 复杂概念,进阶变量,作用域,内存...

网友评论

      本文标题:五、复杂类型

      本文链接:https://www.haomeiwen.com/subject/gzbwkftx.html