参考:http://www.runoob.com/go/go-slice.html

目录

  • 切片
  • 字典(map)
  • 函数(func)
  • 接口(interface)
  • 通道(chan)

四、切片(Slice)

Go 语言切片是对数组的抽象。

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

声明一个未指定大小的数组来定义切片:

var identifier []type

带有 T 类型元素的切片由 []T 表示,其中T代表slice中元素的类型。切片在内部可由一个结构体类型表示,形式如下:

type slice struct {
Length int
Capacity int
ZerothElement *byte
}

可见一个slice由三个部分构成:指针、长度和容量。指针指向第一个slice元素对应的底层数组元素的地址。长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。通过len和cap函数分别返回slice的长度和容量。

切片和数组的区别

  1. 数组声明需要指定元素类型及元素个数 (数组长度必须是整数且大于 0),语法格式:var variable_name [SIZE] variable_type
  2. 声明一个未指定大小的数组来定义切片(切片不需要说明长度),语法格式:var identifier []type
  3. 切片不是数组,但是切片底层指向数组
  4. 切片本身长度是不一定的因此不可以比较,数组是可以的
  5. 切片是变长数组的替代方案,可以关联到指向的底层数组的局部或者全部
  6. 切片是引用传递(传递指针地址),而数组是值传递(拷贝值)
  7. 切片可以直接创建,引用其他切片或数组创建
  8. 如果多个切片指向相同的底层数组,其中一个值的修改会影响所有的切片

Demo 代码

package main

import "fmt"

func main() {
//def & init 1
s1 := []float32{1.2, 1.3, 4.0, 7, 10}
fmt.Println("s1 = ", s1) //def & init 2
s2 := s1[2:4]
fmt.Println("s2 = ", s2) //def & init 3
s3 := s1[:4]
fmt.Println("s3 = ", s3)
}

执行结果

demo2

package main

import "fmt"

func main() {

	/* [1] 初始化数组,初始化数组中 {} 中的元素个数不能大于 [] 中的数字*/
var arr1 = [5]float32{1.2,3.4,5.6,4.4,6.6} //必须指定数组大小 // [2] 如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小
var arr2 = [...]int{1,3,5,7,9,11} /* [3] 数组元素可以通过索引(位置)来读取。格式为数组名后加中括号,中括号中为索引的值*/
fmt.Println("-------打印数组1:",arr1[1])
fmt.Println("-------打印数组2:",arr2[1])
fmt.Printf("-------开始切片----------\n") /* [4] 切片的字面值和数组字面值很像,不过切片没有指定元素个数*/
slice1 := []float32{1.2,3.4,5.6,4.4,6.6} /* 使用make函数创建切片 */
// func make([]T, len, cap) []T : T 代表被创建的切片元素的类型。函数 make 接受一个类型、一个长度和一个可选的容量参数。调用 make 时,内部会分配一个数组,然后返回数组对应的切片。
slice2 := make([]int,5,10) // 使用内置函数 len 和 cap 获取切片的长度和容量信息
fmt.Printf("------获取切片 slice1 的长度和容量信息 len=%d cap=%d slice=%v\n",len(slice1),cap(slice1),slice1)
fmt.Printf("------获取切片 slice2 的长度和容量信息 len=%d cap=%d slice=%v\n",len(slice2),cap(slice2),slice2) // 零值的切片类型变量为 nil。对于零值切片变量,len 和 cap 都将返回 0。
b := []byte{'g', 'o', 'l', 'a', 'n', 'g'} // len=6 cap=6 slice=[103 111 108 97 110 103]
slice3 := []int{1,2,3,4,5,6,7}
fmt.Printf("------获取切片 b 的长度和容量信息 len=%d cap=%d slice=%v\n",len(b),cap(b),b)
fmt.Printf("------获取切片 slice3 的长度和容量信息 len=%d cap=%d slice=%v\n",len(slice3),cap(slice3),slice3)
}

执行结果

切片截取

package main

import "fmt"

func main() {
/* 创建切片 */
numbers := []int{0,1,2,3,4,5,6,7,8}
printSlice(numbers) /* 打印原始切片 */
fmt.Println("numbers ==", numbers) /* 打印子切片从索引1(包含) 到索引4(不包含)*/
fmt.Println("numbers[1:4] ==", numbers[1:4]) /* 默认下限为 0*/
fmt.Println("numbers[:3] ==", numbers[:3]) /* 默认上限为 len(s)*/
fmt.Println("numbers[4:] ==", numbers[4:]) numbers1 := make([]int,0,5)
printSlice(numbers1) /* 打印子切片从索引 0(包含) 到索引 2(不包含) */
number2 := numbers[:2]
printSlice(number2) /* 打印子切片从索引 2(包含) 到索引 5(不包含) */
number3 := numbers[2:5]
printSlice(number3) } // 参数为一个切片
func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法。

package main

import "fmt"

func main() {
var numbers []int
printSlice(numbers) //允许追加空切片
numbers = append(numbers, 0)
printSlice(numbers) /* 向切片添加一个元素 */
numbers = append(numbers, 12)
printSlice(numbers) /* 同时添加多个元素 */
numbers = append(numbers, 100, 200, 4000)
printSlice(numbers) /* 创建切片 numbers1 是之前切片的两倍容量*/
numbers1 := make([]int, len(numbers), (cap(numbers))*2) /* 拷贝 numbers 的内容到 numbers1 */
copy(numbers1, numbers)
printSlice(numbers1)
} // 参数为一个切片
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

更多了解:Go基础Slice教程详解

五、字典(map)

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

定义 Map

可以使用内建函数 make 也可以使用 map 关键字来定义 Map

var map_variable map[key_data_type]value_data_type

代码

package main

import "fmt"

func main() {

        var map_hostip map[string]string
map_hostip = make(map[string]string) map_hostip["host31"] = "192.168.32.131"
map_hostip["host32"] = "192.168.32.132"
map_hostip["host33"] = "192.168.32.133"
map_hostip["host34"] = "192.168.32.134" fmt.Println("map_hostip = ", map_hostip)
fmt.Println("map_hostip[host31] = ", map_hostip["host31"]) }

执行结果

案例2

package main

import "fmt"

func main() {

	// [1] 声明map 语法:var map_variable map[key_data_type]value_data_type
var map1 map[string]string /* 使用make函数创建一个非nil的map(创建集合),nil map不能赋值 */
map1 = make(map[string]string) /* 给已声明的map赋值 */
map1["name"] = "Tinywan"
map1["age"] = "24" /* [2] 直接创建map */
map2 := make(map[string]string)
/* 赋值 */
map2["name"] = "Tinyaiai"
map2["age"] = "25" /* [3] 初始化 + 赋值一体化 */
map3 := map[string]string{
"name": "ShaoBo Wan",
"age": "26",
} /* 使用 key 输出 map 值 */
fmt.Printf("-------遍历 map1---------\n")
for name := range map1 {
fmt.Println("map1 of", name, "is", map1[name])
} // 遍历 map2
fmt.Printf("-------遍历 map2---------\n")
for k, v := range map2 {
fmt.Println(k, v)
} // 遍历 map3
fmt.Printf("-------遍历 map3---------\n")
for k, v := range map3 {
fmt.Println(k, v)
} // 查找键值是否存在
fmt.Printf("-------查找键值是否存在---------\n")
if v, ok := map1["name"]; ok {
fmt.Println("存在", v)
} else {
fmt.Println("Key Not Found")
} /* 删除元素 */
delete(map3, "age")
fmt.Printf("--------删除后的 map3--------\n") // 遍历 map3
for k, v := range map3 {
fmt.Println(k, v)
}
}

执行结果

六、函数(func)和接口(interface)

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。

代码

package main

import "fmt"

// 定义结构体
type person struct {
id int
name string
country string
} // 定义接口
type interface_person interface {
introduction()
} //实现接口方法 使用指针访问
func (this *person) introduction() {
fmt.Println("My name is : ", this.name)
} func main() { var Tinywan person
Tinywan.id = 13669361192
Tinywan.name = "ShaoBo Wan"
Tinywan.country = "China" fmt.Println("Tinywan = ", Tinywan) Tinywan.introduction()
}

说明:在上面的例子中,我们定义了一个接口 interface_person,接口里面有一个方法introduction()。然后我们在main函数里面定义了一个Tinywan类型变量,并分别为之赋值。然后调用introduction()方法

执行结果:

接口

Interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。

interface类型默认是一个指针。

Interface定义:

type Car interface {
NameGet() string
Run(n int)
Stop()
}

Interface实现:

Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement类似的关键字;

如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口;如果一个变量只含有了1个interface的方部分方法,那么这个变量没有实现这个接口。

多态

一种事物的多种形态,都可以按照统一的接口进行操作。

package main

import "fmt"

// 定义Car 接口
type Car interface {
NameGet() string
Run(n int)
Stop()
} // 宝马结构体
type BMW struct {
Name string
} // 实现方法
func (this *BMW) NameGet() string {
return this.Name
} func (this *BMW) Run(n int) {
fmt.Printf("BMW is running of num is %d \n", n)
} func (this *BMW) Stop() {
fmt.Printf("BMW is stop \n")
} // 大奔 结构体
type Benz struct {
Name string
} func (this *Benz) NameGet() string {
return this.Name
} func (this *Benz) Run(n int) {
fmt.Printf("Benz is running of num is %d \n", n)
} func (this *Benz) Stop() {
fmt.Printf("Benz is stop \n")
} func (this *Benz) ChatUp() {
fmt.Printf("ChatUp \n")
} func main() {
var car Car /* 声明 car 为 Car 类型 */
fmt.Println(" car is = ", car)
fmt.Println("-----------------------\r\n") var bmw BMW = BMW{Name: "宝马"}
car = &bmw
fmt.Println(car.NameGet()) //宝马
car.Run(1) // BMW is running of num is 1
car.Stop() // BMW is stop
fmt.Println("-----------------------\r\n") benz := &Benz{Name: "大奔"}
car = benz
fmt.Println(car.NameGet()) //大奔
car.Run(2) //Benz is running of num is 2
car.Stop() //Benz is stop
}

参考:浅谈Go语言中的结构体struct & 接口Interface & 反射

六、通道(chan)

参考:http://blog.csdn.net/u013870094/article/details/74276726

通道是go所特有的数据类型之一,详细地使用方法需要结合通道的长度/容量/单向或双向等才能更好地理解的这样一种通信手段。

声明一个通道很简单,我们使用 chan 关键字即可,除此之外,还要指定通道中发送和接收数据的类型,这样我们才能知道,要发送什么类型的数据给通道,也知道从这个通道里可以接收到什么类型的数据。

ch:=make(chan int)

通道类型和Map这些类型一样,可以使用内置的 make 函数声明初始化,这里我们初始化了一个 chan int 类型的通道,所以我们只能往这个通道里发送 int 类型的数据,当然接收也只能是 int 类型的数据。

代码

package main

import "fmt"

func main() {
fmt.Println("function begins ... ")
c := make(chan bool)
go func() {
fmt.Println("func has been called.")
close(c)
}()
<-c
fmt.Println("Completed.")
}

执行结果

Golang入门教程(九)复合数据类型使用案例二的更多相关文章

  1. 无废话ExtJs 入门教程九[数字字段:NumberField、隐藏字段Hidden、日期字段:DataFiedl]

    无废话ExtJs 入门教程九[数字字段:NumberField.隐藏字段Hidden.日期字段:DataFiedl] extjs技术交流,欢迎加群(201926085) 继上第六节内容,我们在表单里加 ...

  2. RabbitMQ入门教程(九):首部交换机Headers

    原文:RabbitMQ入门教程(九):首部交换机Headers 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog ...

  3. SeaJS入门教程系列之使用SeaJS(二)

    SeaJS入门教程系列之使用SeaJS(二) 作者: 字体:[增加 减小] 类型:转载 时间:2014-03-03我要评论 这篇文章主要介绍了SeaJS入门教程系列之使用SeaJS,着重介绍了SeaJ ...

  4. .NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二)

    原文:.NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二) 先上项目解决方案图: 以上可以看出项目结构可以划分为4大块,1是surging的核心底层,2,3,4都可以 ...

  5. CPF 入门教程 - 数据绑定和命令绑定(二)

    CPF netcore跨平台UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) 数据绑定和Wpf类似,支持双向绑定.数据绑定和命令绑定是UI和业务逻辑分离的基础 ...

  6. Golang入门教程(六)关键字和数据类型

    在 Go 编程语言中,数据类型用于声明函数和变量. 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存. 一.25个关键字 二.18 ...

  7. Spring Cloud 入门教程(九): 路由网关zuul

    在微服务架构中,需要几个关键的组件,服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个组件可以组建一个简单的微服务架构.客户端的请求首先经过负载均衡(zuul.Ngnix),再 ...

  8. Golang入门教程(八)复合数据类型使用案例一

    目录 数组 指针 结构体(struct) 一.数组 Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定 ...

  9. Golang入门教程(七)基本数据类型使用案例

    18种基本数据类型使用 代码案例1 package main import "fmt" func main() { //使用 var 定义一个布尔类型并且初始化 var flag ...

随机推荐

  1. 【CF1097F】Alex and a TV Show(bitset)

    [CF1097F]Alex and a TV Show(bitset) 题面 洛谷 CF 题解 首先模\(2\)意义下用\(bitset\)很明显了. 那么问题在于怎么处理那个\(gcd\)操作. 然 ...

  2. 【转】void 详解

    void关键字的使用规则: 1. 如果函数没有返回值,那么应声明为void类型: 2. 如果函数无参数,那么应声明其参数为void: 3. 如果函数的参数可以是任意类型指针,那么应声明其参数为void ...

  3. dns配置文件

    /etc/resolv.conf 该文件是DNS域名解析的配置文件,它的格式很简单,每行以一个关键字开头,后接配置参数. resolv.conf的关键字主要有四个,分别是: nameserver   ...

  4. [SCOI2016]萌萌哒(倍增+并查集)

    一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1 ...

  5. 单片机的外围功能电路 LET′S TRY“嵌入式编程”: 2 of 6

    单片机的外围功能电路 LET′S TRY“嵌入式编程”: 2 of 6 本连载讲解作为嵌入式系统开发技术人员所必需具备的基础知识.这些基础知识是硬件和软件技术人员都应该掌握的共通技术知识. 上期在&l ...

  6. 源码分析-AutoCloseable

    AutoCloseable 该接口用于try-with-resources语法糖提供支持,用于自动关闭资源作用 类型:接口 方法:close(); 详解: close():用于自动关闭资源的时候需要进 ...

  7. Hyper-V:无法打开虚拟机XXX,因为虚拟机监控程序未运行

    异常处理汇总-服务器系列:http://www.cnblogs.com/dunitian/p/4522983.html 异常处理汇总-开发工具  http://www.cnblogs.com/duni ...

  8. [CTSC2010]性能优化

    [CTSC2010]性能优化 循环卷积快速幂 两个注意点:n+1不是2^k*P+1形式,任意模数又太慢?n=2^k1*3^k2*5^k3*7^k4 多路分治!深刻理解FFT运算本质:分治,推式子得到从 ...

  9. poj3349 Snowflake Snow Snowflakes

    吼哇! 关于开散列哈希: 哈希就是把xxx对应到一个数字的东西,可以理解成一个map<xxx, int>(是不是比喻反了) 我们要设计一个函数,这个函数要确保同一个东西能得到相同的函数值( ...

  10. bzoj3238 差异

    题目链接 思路 观察题目中的式子,可以发现前两项是定值.所以只需要求出最后一项就行了. 然后题目就转化为了求字符串中所有后缀的\(lcp\)长度之和. 可以想到用后缀数组.在后缀数组上两个后缀的\(l ...