【Day 2】跟着Google学Go——A Tour of Go

在这里插入图片描述
图片来源:samjoule/Shutterstock


Day 2:

Go语言存在指针类型,指针保存了值的内存地址,
*T表示指向类型T的指针,其空值为nil
&操作符生成一个指向操作数的指针
*操作符表示指针的值
和C语言不同,Go没有指针算法
在这里插入图片描述
Go和C一样也有结构体Structs,结构体是元素的集合
在这里插入图片描述
访问结构体的成员变量(字段)的方法是使用点
在这里插入图片描述
结构体字段可以通过结构体指针访问
在这里插入图片描述
结构体字面量(literals)有点类似于Python中对类的实例化,众所周知Go中没有class关键字在这里插入图片描述
Go中的数组和Python中的列表和元组很像,不过在声明数组时需要指定数组的长度以及数组值的类型
在这里插入图片描述
数组是定长的,因而其使用收到很大限制,切片可以看成是变长的数组,切片规则和python一致为半开区间
在这里插入图片描述
切片类似为对数组的引用,它不存储任何数据,只描述数组。对切片所指的数据进行修改,会影响到:

  1. 源数组
  2. 其他引用该数组的切片
    在这里插入图片描述
    切片字面量类似于没有长度的数组字面量
// 数组字面量
[3]bool{true, true, false}
// 切片字面量
[]bool{true, true, false}

在这里插入图片描述
切片默认值就是在切片左右边界值缺失时的默认值,切片默认值和Python中的一样,左边界默认为0,右边界默认为切片长度
在这里插入图片描述
切片的长度和容量是切片的两个属性

  • 长度是指切片中元素的个数
  • 容量是指基础数组的元素个数,从切片中第一个元素开始计算
    所以就造成s[2:]会改变切片的容量

使用len(s)、cap(s)分别获取切片的长度和容量
可以通过重切片来增加切片的长度,但是需要在可用的容量范围内,如果超出容量范围则会报错

panic: runtime error: slice bounds out of range [:10] with capacity 4

这部分内容和Python的不太一样,需要多理解一下

注意:你可能不太理解为什么第19行输出的会是[5 7]而不是[5 7 11 13],这是因为此时的s长度为4、容量为6,而切片右默认值为切片的长度,所以第19行输出的其实是[2:4]
在这里插入图片描述
切片的空值为nil,空的切片长度和容量都为0,并且没有基础数组
在这里插入图片描述
切片可以通过内置函数make生成,这是生成动态长度数组的方式
语法为make([]{T}, {len}, {cap})

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

注意,cap可以缺省,缺省则cap(a) = len(a)
在这里插入图片描述
切片元素可以是任何类型,甚至包含其他切片,这有点类似Python中列表包含列表
在这里插入图片描述
三维切片:

package main

import (
	"fmt"
)

func main() {
	// Create a tic-tac-toe board.
	board := [][][]string{
		[][]string{
			[]string{"_", "_", "_"},
			[]string{"_", "_", "_"},
			[]string{"_", "_", "_"},
		},
		[][]string{
			[]string{"_", "_", "_"},
			[]string{"_", "_", "_"},
			[]string{"_", "_", "_"},
		},
		[][]string{
			[]string{"_", "_", "_"},
			[]string{"_", "_", "_"},
			[]string{"_", "_", "_"},
		},
	}
	fmt.Println(board)
}
[[[_ _ _] [_ _ _] [_ _ _]] [[_ _ _] [_ _ _] [_ _ _]] [[_ _ _] [_ _ _] [_ _ _]]]

Go提供内置函数append来给切片添加元素,类似Python列表的append方法。
如果切片s的基本数组容量不够接收新元素,则新的切片会指向新的数组
在这里插入图片描述
for循环的range形式使得能够在切片或字典上进行迭代,每次迭代返回两个值,第一个为索引,第二个为该索引对应值的拷贝。这点与Python中的range形式不太一样,反而和enumerate比较相似
在这里插入图片描述
和Python中类似,可以用单下划线代表不需要的变量
如果只想要索引,而不想要值,则可以将第二个变量完全省略
在这里插入图片描述
这个练习很容易理解,就是要让你构造一个长度为dy,每个元素为dx长度切片的切片,切片中的切片元素中的每个元素为函数(x+y)/2,x*y和x^y的值。但令人迷惑的是main函数中传入pic.Show函数的是Pic函数,而Pic函数并没有传入dx和dy参数,ex为此有人在GitHub上发了个issue
https://github.com/golang/tour/issues/1042
具体原因就是pic.Show这个函数很特殊,看完源码就能理解了https://github.com/golang/tour/blob/master/pic/pic.go#L27

func Show(f func(dx, dy int) [][]uint8) {
	const (
		dx = 256
		dy = 256
	)
	data := f(dx, dy)
	m := image.NewNRGBA(image.Rect(0, 0, dx, dy))
	for y := 0; y < dy; y++ {
		for x := 0; x < dx; x++ {
			v := data[y][x]
			i := y*m.Stride + x*4
			m.Pix[i] = v
			m.Pix[i+1] = v
			m.Pix[i+2] = 255
			m.Pix[i+3] = 255
		}
	}
	ShowImage(m)
}

在这里插入图片描述
和Python一样,Go也有map,为了和Python的字典区别开,我们称其为映射,基于哈希表的键值映射
映射的0值为nil,nil映射没有键而且不能添加键,使用make方法可以返回能够使用的映射
注意:通过

var m map[string]Vertex

声明的映射m无法使用,因为是nil映射,需要

m = make(map[string]Vertex)

此时才能添加键
在这里插入图片描述
在结构体字面量前加上键就成了映射字面量
在这里插入图片描述
如果顶级类型仅是一个类型名,则元素中字面量的类型名可以省略
在这里插入图片描述

  • 插入或者更新元素:
m[key] = elem
  • 检索一个元素:
elem = m[key]
  • 删除一个元素
delete(m, key)
  • 测试映射中是否存在某键
elem, ok = m[key]

如果存在则elem为值,ok为true;如果不存在则elem为元素对应类型的0值,ok为false
在这里插入图片描述
这个练习是要统计所给字符串中单词的出现次数,需要使用strings.Fields方法
在这里插入图片描述
在这里插入图片描述
函数也是值,所以可以像其他值一样被传递
函数值也可以当作函数参数并且返回值
在这里插入图片描述
Go的函数可以是闭包。
关于闭包可以参考:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
https://www.zhihu.com/question/34210214
在这里插入图片描述
使用闭包生成斐波那契数列
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值