30分钟搞定GO语言(三)



基础

一开始,将学习关于语言的所有基础内容。学习如何基于已有类型定义新的类型:盖了结构体、数组、slice 和 map。


指针

Go 具有指针。 指针保存了变量的内存地址。

类型 *T 是指向类型 T 的值的指针。其零值是 nil 。

var p *int

& 符号会生成一个指向其作用对象的指针。

i := 42
p = &i

* 符号表示指针指向的底层的值。

fmt.Println(*p) // 通过指针 p 读取 i
*p = 21         // 通过指针 p 设置 i

这也就是通常所说的“间接引用”或“非直接引用”。


与 C 不同,Go 没有指针运算。


结构体

一个结构体( struct )就是一个字段的集合。

(而 type 的含义跟其字面意思相符。)


结构体字段

结构体字段使用点号来访问。


结构体指针

结构体字段可以通过结构体指针来访问。

通过指针间接的访问是透明的。


结构体文法

结构体文法表示通过结构体字段的值作为列表来新分配一个结构体。

使用 Name: 语法可以仅列出部分字段。(字段名的顺序无关。)

特殊的前缀 & 返回一个指向结构体的指针。


数组

类型 [n]T 是一个有 n 个类型为 T 的值的数组。

表达式

var a [10]int

定义变量 a 是一个有十个整数的数组。


数组的长度是其类型的一部分,因此数组不能改变大小。 这看起来是一个制约,但是请不要担心; Go 提供了更加便利的方式来使用数组。


Slice

数组具有固定大小。另一方面,slice是对数组元素的特殊处理,动态大小,数组元素视图选取灵活。在实践中,切片比数组更常见。


类型[]T是类型的元素的slice T。本质上就是不指定大小。

这个表达式创建数组的第一个五行片a:

a [0:5]


Slice类似于数组的引用

slice不存储任何数据,它只是描述了底层数组的一部分。

更改切片的元素会修改其底层数组的相应元素。共享相同底层数组的其他slice将看到这些更改。


Slice文本

slice文本相当于数组文本去掉了指定长度。

下面是一个数组文本:

[3]bool{true, true, false}

下面是一个slice文本,这个slice文本先内部创建了一个如上的数组,然后创建了一个slice结构指向了内部的数组:

[]bool{true, true, false}


Slice 边界默认值

当选择slice的范围时,你可以忽略声明低边界或者高边界。低边界的默认值是0,高边界的默认值是数组的长度。

对下面的数组来说:

var a [10]int

以下的slice表达式是相等的:

a[0:10]
a[:10]
a[0:]
a[:]


Slice的长度和容量


slice既有长度又有容量。

slice的长度是它包含的元素数。slice的容量是底层数组中元素的数量,从slice中的第一个元素计数。

slice的长度和容量可以使用表达式得到len(s)和cap(s)。


只要有足够的容量,就可以通过重新切片来延长slice的长度。如果slice调整后的长度,超出底层的数组的长度,则会报错:

panic: runtime error: slice bounds out of range



Nil Slice

slice 的零值是 nil 。

一个 nil 的 slice 的长度和容量是 0,并且没有底层相关联的array。


构造 slice

slice 由函数 make 创建,通过这个内置函数可以创建动态长度的数组。

这会分配一个全是零值的数组并且返回一个 slice 指向这个数组:

a := make([]int, 5)  // len(a)=5

为了指定容量,可传递第三个参数到 make:

b := make([]int, 0, 5) // len(b)=0, cap(b)=5

b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:]      // len(b)=4, cap(b)=4


Slices of slices

Slice能够包含任何类型,包括其他的slice.


向 slice 添加元素

向 slice 的末尾添加元素是一种常见的操作,因此 Go 提供了一个内建函数 append 。 内建函数的文档对 append 有详细介绍。

func append(s []T, vs ...T) []T

append 的第一个参数 s 是一个元素类型为 T 的 slice ,其余类型为 T 的值将会附加到该 slice 的末尾。


append 的结果是一个包含原 slice 所有元素加上新添加的元素的 slice。

如果 s 的底层数组太小,而不能容纳所有值时,会分配一个更大的数组。 返回的 slice 会指向这个新分配的数组。

(了解更多关于 slice 的内容,参阅文章https://blog.go-zh.org/go-slices-usage-and-internals)


Range

for 循环的 range 格式可以对 slice 或者 map 进行迭代循环。

当使用 for 循环遍历一个 slice 时,每次迭代 range 将返回两个值。 第一个是当前下标(序号),第二个是该下标所对应元素的一个拷贝。

可以通过赋值给 _ 来忽略索引或值。


如果只需要索引值,去掉 “ , value ” 的部分即可。

做一个练习,这个练习的代码我结合了指针一起。实现 Pic 。它返回一个长度为 dy 的 slice,其中每个元素是一个长度为 dx 且元素类型为8位无符号整数的 slice。当你运行这个程序时, 它会将每个整数作为对应像素的灰度值(好吧,其实是蓝度)并显示这个 slice 所对应的图像。


计算每个像素的灰度值的方法由你决定;几个有意思的选择包括 (x+y)/2、x*y 和 x^y 。

(需要使用循环来分配 [][]uint8 中的每个 []uint8 。)

(使用 uint8(intValue) 来在类型之间进行转换。)


Map

Map 映射键到值。Map的零值是nil. 一个nil的map没有键,也不能添加键。 map 在使用之前须用 make 来创建,会自动完成初始化;


Map 的文本

map 的文本跟结构体文本相似,不过必须有键名。


若顶级类型只是一个类型名,你可以在文法的元素中省略它。


修改 Map

在 map m 中插入或修改一个元素:

m[key] = elem

获得元素:

elem = m[key]

删除元素:

delete(m, key)

通过双赋值检测某个键存在:

elem, ok = m[key]

如果 key 在 m 中, ok 为 true。否则, ok 为 false,并且 elem 是 map 的元素类型的零值。


同样的,当从 map 中读取某个不存在的键时,结果是 map 的元素类型的零值。

如果elem和ok之前没有被声明,可以直接使用自动类型推导

elem, ok := m[key]


做一个练习,实现 WordCount。它应当返回一个含有 s 中每个 “词” 个数的 map。函数 wc.Test 针对这个函数执行一个测试用例,并输出成功还是失败。


函数值

函数也是值。他们可以像其他值一样传递,同样,函数值可以作为函数的参数或者返回值。


函数的闭包

Go 函数可以是一个闭包。闭包是一个函数值,它引用了函数体之外的变量。 这个函数可以对这个引用的变量进行访问和赋值;换句话说这个函数被“绑定”在这个变量上。

例如,函数 adder 返回一个闭包。每个返回的闭包都被绑定到其各自的 sum 变量上。

现在来通过函数做些有趣的事情。


实现一个 fibonacci 函数,返回一个函数(一个闭包)可以返回连续的斐波纳契数。


◆  ◆  ◆  ◆  ◆  

来源:

作者介绍:张洋铭,投资人中最懂动漫的程序员,负责PlugandPlay早期科技类项目投资,个人关注动漫智能助理。


微信公众号:张洋铭Ocean(ocean_anidata)

BP请投递至:ocean.zhang@plugandplaychina.com

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 出处---Go编程语言 欢迎来到 Go 编程语言指南。本指南涵盖了该语言的大部分重要特性 Go 语言的交互式简介,...
    Tuberose阅读 18,396评论 1 46
  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,422评论 3 44
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,204评论 0 4
  • Hello World这是开发的一个开发魔咒,几乎所有人都是从这开始的,今天我也从魔咒开始先打印一份Hello W...
    cocoaAhda阅读 1,429评论 0 3
  • 选一首歌,陪我过夜半。 选一曲歌,陪我孤单。 我是怎么样的夜半不眠。 不在乎别人说的什么,坚持自己要做的。不怕别人...
    金不换jbh阅读 318评论 0 0