Go语言基础:make,new, len, cap, append, delete方法
2017-07-06 08:50
1581 查看
前面提到不少go的内建函数,这篇文章学习下如何使用。。
于是找度娘,一点信息都没有。还是 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 有介绍,这里直接贴出来:
例子:
输出:
对于make slice而言,有两个概念需要搞清楚:长度跟容量。
容量表示底层数组的大小,长度是你可以使用的大小。
容量的用处在哪?在与当你用 appen d扩展长度时,如果新的长度小于容量,不会更换底层数组,否则,go 会新申请一个底层数组,拷贝这边的值过去,把原来的数组丢掉。也就是说,容量的用途是:在数据拷贝和内存申请的消耗与内存占用之间提供一个权衡。
而长度,则是为了帮助你限制切片可用成员的数量,提供边界查询的。所以用 make 申请好空间后,需要注意不要越界【越 len 】
但是我们用 new 分配的空间,函数返回的是一个指向新分配的零值的指针。函数格式如下:
例子
输出:
如果 v 是数组:返回的是数组的元素个数
如果 v 是个指向数组的指针:返回的是 *v 的元素个数
如果 v 是 slice 或者 map :返回 v 的元素个数
如果 v 是 channel:the number of elements queued (unread) in the channel buffer;因还不清楚 channel 是啥,就网上直接搬过来
数组:返回的是数组的元素个数,同 len(v)
指向数组的指针:返回的是 *v 的元素个数,同 len(v)
slice:返回的是 slice 最大容量,>=len(v)
channel: the channel buffer capacity, in units of element
第一种用法中,第一个参数为 slice ,后面可以添加多个参数。
如果是将两个 slice 拼接在一起,则需要使用第二种用法,在第二个 slice 的名称后面加三个点,而且这时候 append 只支持两个参数,不支持任意个数的参数。
个人感觉方法2用得多些
例子1【采用方法1】:
输出:
例子2【采用方法1】:
输出:
函数结构:
例子
输出:
基本上前面所遇到的函数,这里都有了简单的说明。
参考:
https://wizardforcel.gitbooks.io/golang-stdlib-ref/content/6.html#make
https://golang.org/ref/spec#Making_slices_maps_and_channels
http://www.oschina.net/translate/go-lang-slices
本文来自:CSDN博客
感谢作者:uudou
查看原文:Go语言基础:make,new, len, cap, append, delete方法
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…)
第一种用法中,第一个参数为 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 a437 //注意容量变为了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!]
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 获取
基本上前面所遇到的函数,这里都有了简单的说明。
参考:
https://wizardforcel.gitbooks.io/golang-stdlib-ref/content/6.html#make
https://golang.org/ref/spec#Making_slices_maps_and_channels
http://www.oschina.net/translate/go-lang-slices
本文来自:CSDN博客
感谢作者:uudou
查看原文:Go语言基础:make,new, len, cap, append, delete方法
相关文章推荐
- Go语言基础:make,new, len, cap, append, delete方法
- Go语言基础:make,new, len, cap, append, delete方法
- Go语言基础:array、slice、make和new操作、map
- Go语言学习三:Go基础(iota,array,slice,map,make,new)
- Go 语言中的 new() 和 make() 的区别
- Go语言中new与make的区别
- Go语言中new()和 make()的区别详解
- Go语言学习之new与make(The way to go)
- Go 语言中的 new() 和 make()的区别
- Go 语言中的 new() 和 make()的区别
- Go 语言中的 new() 和 make()的区别
- go语言笔记——go是有虚拟机runtime的,不然谁来做GC呢,总不会让用户自己来new和delete进行内存管理吧,还有反射!Go 的 runtime 嵌入到了每一个可执行文件当中
- 【Go入门教程4】变量(var),常量(const),内置基础类型(Boolean、数值 byte,int,rune、字符串、错误类型),分组,iota枚举,array(数值),slice(切片),map(字典),make/new操作,零值
- go语言的new和make
- Go 语言 make & new
- Go语言中new()和 make()的区别详解
- Go 语言中的 new() 和 make()的区别
- C++语言基础(2)-new和delete操作符
- GO语言基础学习------方法_1
- Go 语言中的 new() 和 make() 的区别