前面提到不少Go的内建函数,这篇文章学习下如何使用。。

make

先拿 make 开刀,可是一开始我就进入了误区,因为我想先找到他的源码,先是发现 src/builtin/builtin.go 中有func make(Type, size IntegerType) Type ,可是这里只有两个参数,跟我所了解的 make 是个可变参数不太一样,于是我继续搜索源码包是否还有其它 make 函数原型的声明,但都是徒劳。 
于是找度娘,一点信息都没有。还是 google 吧,找了一堆的英文解释,发现两个网站解释还可以,具体看How can the golang make function can take three parameters? 和 golang builtin package。 
总的意思是我在源码找到的 builtin.go 只是一个文档,并不是源代码,这些函数是经过特殊处理的,我们不能直接去使用他们。相对于 make 来说,真正的实现是在 runtime 包里面的 makeslice ,具体怎么做到的,那就要研究编译器了,看汇编是如何实现的。 
唉,光make的源码就折腾了我一天的时间,脑袋不够用啊,谁借我一颗脑袋使使。 
好,到这里,虽然没有找到 make 的具体源码,但是知道 make 是没有直接的具体源码的,死心了。 
make 只能为 slice、ma p或 channel 类型分配内存并初始化,同时返回一个有初始值的 slice、map 或 channel 类型引用,不是指针。具体如何使用 make 呢,官网中https://golang.org/ref/spec#Making_slices_maps_and_channels 有介绍,这里直接贴出来:

Call             Type T     Result

make(T, n)       slice      slice of type T with length n and capacity n
make(T, n, m) slice slice of type T with length n and capacity m make(T) map map of type T
make(T, n) map map of type T with initial space for n elements make(T) channel unbuffered channel of type T
make(T, n) channel buffered channel of type T, buffer size n

例子:

package main

import "fmt"

func main() {
slice1 := make([]int, 5)
slice2 := make([]int, 5, 10)
fmt.Println(slice1, len(slice1), cap(slice1))
fmt.Println(slice2, len(slice1), cap(slice2)) map1 := make(map[string]int)
map2 := make(map[string]int, 5) fmt.Println(map1, len(map1))
fmt.Println(map2, len(map2))
}

输出:

[0 0 0 0 0] 5 5
[0 0 0 0 0] 5 10
map[] 0
map[] 0

对于make slice而言,有两个概念需要搞清楚:长度跟容量。

  • 容量表示底层数组的大小,长度是你可以使用的大小。
  • 容量的用处在哪?在与当你用 appen d扩展长度时,如果新的长度小于容量,不会更换底层数组,否则,go 会新申请一个底层数组,拷贝这边的值过去,把原来的数组丢掉。也就是说,容量的用途是:在数据拷贝和内存申请的消耗与内存占用之间提供一个权衡。
  • 而长度,则是为了帮助你限制切片可用成员的数量,提供边界查询的。所以用 make 申请好空间后,需要注意不要越界【越 len 】

new

一样也找不到的具体的原型函数,只在src/builtin/builtin.go中有func new(Type) *Type。根据前面查 make 的具体原型的经验,我猜这个这是 new 的函数格式,具体调用应该是类似于 func newint() *int 这种函数,总之应该还是由编译器链接完成的。 
但是我们用 new 分配的空间,函数返回的是一个指向新分配的零值的指针。函数格式如下:

func new(Type) *Type

例子

    new1 := new([2]int)
fmt.Println(new1)
new1[0] = 1
new1[1] = 2
fmt.Println(new1)

输出:

&[0 0]
&[1 2]

len 和 cap

函数 len 格式:

func len(v Type) int
  • 如果 v 是数组:返回的是数组的元素个数
  • 如果 v 是个指向数组的指针:返回的是 *v 的元素个数
  • 如果 v 是 slice 或者 map :返回 v 的元素个数
  • 如果 v 是 channel:the number of elements queued (unread) in the channel buffer;因还不清楚 channel 是啥,就网上直接搬过来

函数 cap 的格式:

func cap(v Type) int
  • 数组:返回的是数组的元素个数,同 len(v)
  • 指向数组的指针:返回的是 *v 的元素个数,同 len(v)
  • slice:返回的是 slice 最大容量,>=len(v)
  • channel: the channel buffer capacity, in units of element

append

append 将元素追加到切片 slice 的末尾,若它有足够的容量,其目标就会重新切片以容纳新的元素。否则,就会分配一个新的基本数组。append 返回更新后的切片,因此必须存储追加后的结果。

append的用法有两种:

slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice…)
  • 1
  • 2
  • 1
  • 2

第一种用法中,第一个参数为 slice ,后面可以添加多个参数。 
如果是将两个 slice 拼接在一起,则需要使用第二种用法,在第二个 slice 的名称后面加三个点,而且这时候 append 只支持两个参数,不支持任意个数的参数。 
个人感觉方法2用得多些 
例子1【采用方法1】:

slice1 := make([]int, 5, 10)
slice2 = append(slice2, 5, 6, 7, 8, 9)
fmt.Println(slice2, len(slice2), cap(slice2))
slice2 = append(slice2, 10)
fmt.Println(slice2, len(slice2), cap(slice2))

输出:

[0 1 2 3 4 5 6 7 8 9] 10 10
[0 1 2 3 4 5 6 7 8 9 10] 11 20//注意容量变为了20

例子2【采用方法1】:

    d := []string{"Welcome", "for", "Hangzhou, ", "Have", "a", "good", "journey!"}
insertSlice := []string{"It", "is", "a", "big", "city, "}
insertSliceIndex := 3
d = append(d[:insertSliceIndex], append(insertSlice, d[insertSliceIndex:]...)...)
fmt.Println(d)

输出:

[Welcome for Hangzhou,  It is a big city,  Have a good journey!]
  • 1
  • 1

delete

内建函数 delete 按照指定的键将元素从映射中删除。若 m 为 nil 或无此元素,delete 不进行操作。 
函数结构:

func delete(m map[Type]Type1, key Type)

例子

    map1 := make(map[string]int)

    map1["one"] = 1
map1["two"] = 2
map1["three"] = 3
map1["four"] = 4 fmt.Println(map1, len(map1))
delete(map1, "two")
fmt.Println(map1, len(map1))

输出:

map[three:3 four:4 one:1 two:2] 4
map[four:4 one:1 three:3] 3
//map 是无序的,每次打印出来的 map 都会不一样,所以它不能通过 index 获取,而必须通过 key 获取

基本上前面所遇到的函数,这里都有了简单的说明。

Go语言基础:make,new, len, cap, append, delete方法的更多相关文章

  1. C语言基础:两个变量交换值的方法

    学习任何语言基础时,两个数值得交换是必须掌握的,下面是3种不同的方式(c语言) 方法一:利用数学的计算技巧 #include <stdio.h> int main() { , b = ; ...

  2. Go 语言基础

    Go 语言基础 特点 常用命令 go run 直接运行, 不会生成可执行文件 go build 生成可执行文件, 推荐 加分特点 UTF-8编码 高并发: go 关键字 管道: pipe := mak ...

  3. 【GoLang】GO语言系列--002.GO语言基础

    002.GO语言基础 1 参考资料 1.1 http://www.cnblogs.com/vimsk/archive/2012/11/03/2736179.html 1.2 https://githu ...

  4. Go语言基础之切片

    Go语言基础之切片 本文主要介绍Go语言中切片(slice)及它的基本使用. 引子 因为数组的长度是固定的并且数组长度属于类型的一部分,所以数组有很多的局限性. 例如: func arraySum(x ...

  5. Go语言基础之变量和常量

    Go语言基础之变量和常量 变量和常量是编程中必不可少的部分,也是很好理解的一部分. 标识符与关键字 标识符 在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名.常量名.函数名等等. Go语 ...

  6. go语言基础学习

    go基础学习,面向对象-方法在Go语言中,可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法 使用= 和:=的区别: // = 使用必须使用先var声明例如: var a a=100 ...

  7. GO_04:GO语言基础条件、跳转、Array和Slice

    1. 判断语句if 1. 条件表达式没有括号(这点其他语言转过来的需要注意) 2. 支持一个初始化表达式(可以是并行方式,即:a, b, c := 1, 2, 3) 3. 左大括号必须和条件语句或 e ...

  8. GO语言基础条件、跳转、Array和Slice

    1. 判断语句if 1. 条件表达式没有括号(这点其他语言转过来的需要注意) 2. 支持一个初始化表达式(可以是并行方式,即:a, b, c := 1, 2, 3) 3. 左大括号必须和条件语句或 e ...

  9. go学习笔记-语言基础

    语言基础 结构 基础组成: 包声明 引入包 函数 变量 语句 & 表达式 注释 程序 在开始编写应用之前,我们先从最基本的程序开始,在学习大部分语言之前,都会编写一个可以输出hello wor ...

随机推荐

  1. vue iframe嵌套单页面时打开新窗口并自定义浏览器标题

    vue打开新窗口两种写法,效果一样: 第一种: router-link 传参用query或者params都可以,tagget和tag一定要加上才可以: 第二种: 直接写成a标签就可以了. 改变浏览器窗 ...

  2. webpack 导出、导入模块(及路径)

    参考:https://blog.csdn.net/xyphf/article/details/83411552 (下面的代码亲测有效) 注:导入的模块的方法,只有两种方法  import 和 requ ...

  3. Wireshark协议分析1

    一.界面简介   1.抓包工具栏 2.文件工具栏 3.包定位工具栏 4.颜色以及滚动界面工具栏 5.数据包列表字体定义工具栏 6.首选项工具栏 二.过滤规则 1.过滤 IP ip.src eq 192 ...

  4. [CSP-S模拟测试]:字符(模拟+剪枝)

    题目传送门(内部题33) 输入格式 第一行,两个整数$T,C$,表示测试数据组数和字符种类数.对于每组数据:第一行,一个正整数$M$:接下来的$M$行,每行两个整数$P_k,X_k$($S$的下标从$ ...

  5. SPSS输出的结果都要写到文章中吗

    SPSS输出的结果都要写到文章中吗 经常有人问到,SPSS输出的结果都要写到文章中吗?文章中应该写什么呢?比如,均值.中位数.众数.标准差.百分位数.最小值.最大值等等,都要出现在文章中吗?洋洋洒洒那 ...

  6. 图片模式CMYK和RGB在浏览器下的变化

    手机浏览器里面不能显示出模式为CMYK的图片, 模式为CMYK的图片在IE浏览器里面显示和模式为RGB的一样 模式为CMYK的图片在火狐里面显示有色差

  7. 使用php的curl函数post返回值为301永久迁移的问题。(301 Moved Permanently)

    本文链接:https://blog.csdn.net/Angus_01/article/details/82467652添加一行curl_setopt: curl_setopt($ch,CURLOPT ...

  8. 基于MFC的Media Player播放器制作的SetTimer函数介绍

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. SetTimer是一种API函数,位于user32.dll中.你想每隔一段时间执行一件事的的时候,你可以使用它. 使用定时器的方法比 较简 ...

  9. Matplotlib ValueError: _getfullpathname: embedded null character

    Traceback (most recent call last): File "<stdin>", line 1, in <module> File &q ...

  10. sql 查询库是否存在

    网上查了很多,但是都是不完整的,很多坑,后面终于摸索出来了:DROP DATABASE IF EXISTS 库名(不要加引号); 这句话的意思就是如果库存在,就删除库,然后再新建库就行了.