Go语言学习笔记2019.11.28


复合类型

分类

0秒抢红包:  (1)凡本网注明“来源:中国新闻网”或带有“中新社”和“中新网”电头的所有文字、加盖“中新社”及“中新网”水印且注明“中新社发****摄”、“中新社记者****摄”或“中新网记者****摄”的图片稿件、来源为“中国新闻网”或视频画面上标有“中新社”、“中新网”、“CNSTV”的视频,版权均属中新社和中新网所有,未经本网书面授权,任何媒体、网站或个人不得转载、链接、转贴或以其他方式使用。

类型 | 名称 | 长度 | 默认值 | 说明
pointer | 指针 | | nil |
array | 数组 | | 0 |
slice | 切片 | | nil | 引用类型
map | 字典 | | nil | 引用类型
struct | 结构体 | | |

指针

指针是代表某个内存地址的值,这个内存地址往往是在内存中存储的另一个变量的值的起始位置。

基本操作

func main() {
    var a int = 10
    // 每个变量有两层含义:变量的内存和变量的地址
    fmt.Printf("a = %d\n", a)  // 变量的内存
    fmt.Printf("a = %v\n", &a)  // 变量的地址
    
    // 保存某个变量的地址,需要指针类型 
    // *int 用以保存 int 的地址
    // **int 用以保存 *int 的地址
    var p *int
    p = &a // 指针变量指向谁,就把谁的地址赋值给指针变量
    
    *p = 666 // *p操作的不是p的内存,而是p所指向的内存(既是a)
}

不要操作没有合法指向的内存。

new函数

var p *int //指向一个合法内存
p = new(int) // p是*int,指向int类型
*p = 666
q := new(int) // 自动推导类型
*q = 777

地址传递

func swap(p1, p2 *int) {
    *p1, *p2 = *p2, *p1
}
func main() {
    a, b := 10, 20
    
    swap(&a, &b)
}

数组

为什么需要数组

数组:同一类型数据的集合。
通过下标操作数组,从0开始,到 len()-1

数组定义

func main() {
    // 定义一个数组,[10]int和[5]int是不同类型
    // [数字],这个数字作为数组元素个数
    var a [10]int
    var b [5]int
    // 注意:定义数组时,指定的数组元素个数必须是常量
    // 数组下标可以是变量或常量
}

数组初始化

初始化:声明定义的同时赋值

func main() {

    // 全部初始化
    var a [5]int = [5]int{1, 2, 3, 4, 5}
    b := [5]int{1, 2, 3, 4, 5}
    
    // 部分初始化,没有初始化的元素自动赋值为0
    c := [5]int{1, 2, 3}
    
    // 指定某个元素初始化
    d := [5]int{2: 10, 4: 20 }
}

二维数组

var a [3][4]int
var b [3][4]int
b := [3][4]int{{1,2,3,4},    {5,6,7,8},    {9,10,11,12}}
// 部分初始化,没有初始化的为0
b := [3][4]int{{1,2,3,4},    {5,6,7,8},    {9,10}}

数组比较和赋值

只支持 == 和 != 的比较,用于比较两个数组类型、每个元素都一样。

数组做函数参数

数组做函数参数,是值传递。实参数组的每个元素会给形参拷贝一份。
所以数组越大,传递效率越低。

数组指针做函数参数

p指向实现数组a。※p代表指针所指向的内存,就是实参a。

func modify(p *[5]int) {
    (*p)[0] = 666
}

随机数

两个步骤:

  1. 设置种子(只需一次),如果种子一样,每次运行程序产生的随机数都一样
  2. 产生随机数

种子设置技巧:可以用当前时间作为种子,或者用进程号

import "math/rand"

rand.Seed(666) // time,Now().UnixNano() 系统当前时间
rand.Int() // 随机大数
rand.Intn(100) // 限制在一百以内

数组切片 slice

数组缺点

  1. 数组大小固定,不利于拓展
  2. 数组作为参数时,需要整个数组拷贝,效率较低

数组切片弥补数组不足

切片并不是数组或者数组指针,它通过内部指针和相关属性引用数组片段,以实现变长方案。
slice并不是真正意义上的动态数组,而是一个引用类型。
slice总是指向一个底层array,slice的声明也可以像array一样,只是不需要长度。

a := [...]int{10, 20, 30, 0, 0}
slice := a[0:3:5]
[low:high:max]
low:下标的起点
high:下标的终点(左闭右开,不包括此下标)
cap = max-low ,表示容量
len = high - low ,表示长度

切片和数组的区别

  • 数组[]里面的长度是一个固定的常量,数组不能修改长度,len和cap永远固定
  • 切片里面为空,或者为... ,切片的长度或容量可以不固定

切片的创建

 // 自动推导类型,同时初始化
 s1 := []int{1,2,3,4}

// 借助make函数,格式:make(slice, len, cap) 切片类型,长度,容量
s2 := make([]int, 5, 10)
// 不指定容量时,容量和长度一样
s2 := make([]int, 5)

切片截取

[low:high:max] 取下标从low开始的元素

// 不指定容量,默认和长度一样
s1 = arrar[:]  // 等同于:[0 : len(array) : len(array)]
// 取中间一段
s2 = arrar[3:6:7]  // a[3],a[4],a[5]  len=6-3=3  cap=7-3=4
// 不指定初始位置,默认从0开始 -- 常用这种
s3 = array[:6] // 从0开始,取6个元素,容量也是6
// 不指定结束位置,默认到结尾
s4 = array[3:] // 从下标3开始到结尾

操作切片的某个元素,和数组操作方式一样

data := array[1]

append函数

向原切片末尾添加元素,返回新的slice对象,如果slice空间不足,会自动扩容。

s1 := []int{} // 默认len和cap都为0
s1 = append(s1, 1)
s1 = append(s1, 2)
s1 = append(s1, 3)

扩容特点:如果超过原来的容量,通常以当前容量的2倍扩容。

copy函数

srcSlice := []int{1, 2}
dstSlice := []int{6, 6, 6, 6, 6}
copy(dstSlice, srcSlice) // dstSlice变为[1, 2, 6, 6, 6]

切片做函数

数组是值传递,切片是地址传递。

本文发表于2019年11月28日 21:56
阅读 43 讨论 0 喜欢 0

讨论

周娱

君子和而不同
按照自己的方式,去度过人生

8000 3144442
抢先体验

扫码体验
趣味小程序
文字表情生成器

加入组织

扫码添加周娱微信
备注“加入组织”
邀请进开发群

闪念胶囊

这个世界上,别人只会看你现在的样子而不是以后的样子。你以后的样子只有自己才相信。如果没有执行力,一切都是虚妄。

对普通人来说,人和人相处其实最重要的是感觉。感觉不好,你说什么都没用,怎么解释都没用,越说越错,反正最后不好的锅都往你身上扣。所谓“说你行你就行,不行也行。说你不行,你就不行,行也不行”就是这个意思。狼要吃人根本不需要理由,你也同样叫不醒装睡的人。遇到这种情况,早点闪人才是上策。不过大部分人的问题是没有闪人的心态,能力,和资源。

考985不牛逼,考上才牛逼。创业不牛逼,创业成功才牛逼。这个社会上很多人把目标当成牛逼的资本,牛逼哄哄的,死活不听劝,然后做的一塌糊涂,给别人添麻烦,让别人帮他料理后事,对此只能呵呵。

当你尝到用生气解决问题的甜头后,你就懒得再用其他方式了。你却忽略了,生气是鸩毒啊,剂量用够了,你的关系也玩完了。

年轻的时候你只搞事业不谈恋爱,等你事业有成了,钱相对自由了,你可能已经没有荷尔蒙了。

如果你经常雇佣比你矮小的人,将来我们就会变成矮人国,变成一家侏儒公司。相反,如果你每次都雇用比你高大的人,日后我们必能成为一家巨人公司。

如果一个人有充裕的时间去完成一项工作,那么他就会放慢节奏或者增加其他不必要的工作,直到花光所有的时间。

天空不是人类休息的地方,人类应该去亲近海洋。

一个人的正直程度,取决于他肯为原则付出的牺牲。

Copyright ? 2016 - 2018 Cion.
All Rights Reserved.
备案:鲁ICP备16007319号.