golang 切片的三种使用方式及区别的说明

概念

切片(slice)是建立在数组之上的更方便,更灵活,更强大的数据结构。切片并不存储任何元素而只是对现有数组的引用。

三种方式及细节案例

①定义一个切片,然后让切片去引用一个已经创建好的数组

package main
import (
    "fmt"
)
func main() {
    var arr [5]int = [...]int {1, 2, 3, 4, 5}
    var slice = arr[1:3]
    fmt.Println("arr=", arr)
    fmt.Println("slice=", slice)
    fmt.Println("slice len", len(slice))
    fmt.Println("slice cap", cap(slice))
}

②通过make来创建切片

基本语法:var 切片名 []type = make([], len, [cap]);参数说明:type是数据类型、len是大小、cap是切片容量(容量必须>=长度)

通过make方式创建切片可以指定切片大小和容量

如果没有给切片的各个元素赋值,那么就会使用默认值(int、float=>0, strint=>"", bool=>false)

荣国make方式创建的切片对应的数组是由make底层维护,对外不可见,也就是只能通过slice访问各个元素

package main
import (
    "fmt"
)
func main() {
    var slice []float64 = make([]float64, 5, 10)
    //没有给值,默认都是0
    fmt.Println(slice)  //[0 0 0 0 0]

    //赋值
    slice[1] = 5
    slice[3] = 10
    fmt.Println(slice)  //[0 5 0 10 0] 

    fmt.Println("slice大小:", len(slice)) //slice大小: 5
    fmt.Println("slice容量:", cap(slice)) //slice容量: 10
}

③定义一个切片,直接就指定具体数组,使用原理类似于make的方式

package main
import (
    "fmt"
)
func main() {
    var slice []string = []string{"zhangsan", "lisi", "wangwu"}
    fmt.Println("slice=", slice) //slice= [zhangsan lisi wangwu]
    fmt.Println("slice len", len(slice)) //slice len 3
    fmt.Println("slice cap", cap(slice)) //slice cap 3
}

第一种和第二种的区别

第一种方式是直接引用数组,这个数组是事先存在的,程序员可见

第二种方式是通过make来创建切片,make也会创建一个数组,是由切片在底层维护,程序员不可见

补充:零碎案例

package main
import "fmt"
func main() {
    // 和数组不同的是,切片的长度是可变的。
    // 我们可以使用内置函数make来创建一个长度不为零的切片
    // 这里我们创建了一个长度为3,存储字符串的切片,切片元素
    // 默认为零值,对于字符串就是""。
    s := make([]string, 3)
    fmt.Println("emp:", s)

    // 可以使用和数组一样的方法来设置元素值或获取元素值
    s[0] = "a"
    s[1] = "b"
    s[2] = "c"
    fmt.Println("set:", s)
    fmt.Println("get:", s[2])

    // 可以用内置函数len获取切片的长度
    fmt.Println("len:", len(s))

    // 切片还拥有一些数组所没有的功能。
    // 例如我们可以使用内置函数append给切片追加值,然后
    // 返回一个拥有新切片元素的切片。
    // 注意append函数不会改变原切片,而是生成了一个新切片,
    // 我们需要用原来的切片来接收这个新切片
    s = append(s, "d")
    s = append(s, "e", "f")
    fmt.Println("apd:", s)

    // 另外我们还可以从一个切片拷贝元素到另一个切片
    // 下面的例子就是创建了一个和切片s长度相同的新切片
    // 然后使用内置的copy函数来拷贝s的元素到c中。
    c := make([]string, len(s))
    copy(c, s)
    fmt.Println("cpy:", c)

    // 切片还支持一个取切片的操作 "slice[low:high]"
    // 获取的新切片包含元素"slice[low]",但是不包含"slice[high]"
    // 下面的例子就是取一个新切片,元素包括"s[2]","s[3]","s[4]"。
    l := s[2:5]
    fmt.Println("sl1:", l)

    // 如果省略low,默认从0开始,不包括"slice[high]"元素
    l = s[:5]
    fmt.Println("sl2:", l)

    // 如果省略high,默认为len(slice),包括"slice[low]"元素
    l = s[2:]
    fmt.Println("sl3:", l)

    // 我们可以同时声明和初始化一个切片
    t := []string{"g", "h", "i"}
    fmt.Println("dcl:", t)

    // 我们也可以创建多维切片,和数组不同的是,切片元素的长度也是可变的。
    twoD := make([][]int, 3)
    for i := 0; i < 3; i++ {
        innerLen := i + 1
        twoD[i] = make([]int, innerLen)
        for j := 0; j < innerLen; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d: ", twoD)
}

结果

emp: [  ]
set: [a b c]
get: c
len: 3
apd: [a b c d e f]
cpy: [a b c d e f]
sl1: [c d e]
sl2: [a b c d e]
sl3: [c d e f]
dcl: [g h i]
2d:  [[0] [1 2] [2 3 4]]

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • golang 切片截取参数方法详解

    以 s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}为例 0. 建议:做slice截取时建议用两个参数,尤其是从底层数组进行切片操作时,因为这样在进行第一次append操作时,会给切片重新分配空间,这样减少切片对数组的影响. 1. 结论:s = s[low : high : max] 切片的三个参数的切片截取的意义为 low为截取的起始下标(含), high为窃取的结束下标(不含high),max为切片保留的原切片的最大下标(不含max):即新切片从老切片的low

  • golang 字符串切片去重实例

    实现目的:实现字符串切片去重,只是两个字符完全相同时,去除一个. 实现方式:考虑两种,一种是常规的双重循环去除,另一种是利用map的key的唯一性实现. 1.通过双重循环来过滤重复元素 方法1, 思路:利用for双重循环,新建一个slice,遍历原slice中的每一个元素,每一次判断这个元素和后面元素是否相同,若相同则去除,若不同则存入新slice中,判断本元素后,再继续判断下一个元素,直到判断完毕. package main import "fmt" func main() { va

  • golang 删除切片的某个元素及剔除切片内的零值方式

    看代码吧~ func remove(slice []interface{}, elem interface{}) []interface{}{ if len(slice) == 0 { return slice } for i, v := range slice { if v == elem { slice = append(slice[:i], slice[i+1:]...) return remove(slice,elem) break } } return slice } func rem

  • golang-切片slice的创建方式

    在创建一个新的切片是都会先创建一个长度为len的数组,并为其开辟一个cap长度为cap的额外空间,所以在cap范围类增加元素,数组的起始地址不会改变,否则会创建一个新的数组,即起始的位置发生改变 数组创建 代码 intArr:=[...]int{1,2,3,4,5,6,7,9} //方式一指定开始和结束 s:=intArr[1:3] //方式er指定开始和结束+容量 s:=intArr[1:3:6] 创建后的slice [a: b :c] a:起始位置 b:截取数据的结束位置 默认到末端) c:

  • Golang二维切片初始化的实现

    引言 之前,刷Leetcode的时候,有些题需要初始化二维数组,而一维数组的初始化,比如: var a = [5]int{1, 2, 3, 4, 5} // 用var b := [5]int{1, 2, 3, 4, 5} // 用类型推断 var c = [...]int{1, 2, 3, 4, 5} // 不确定长度 d := [...]int{1, 2, 3, 4, 5} 如果不知道数组元素的话,可以这样: var a [5]int b := [5]int{} c := make([]int

  • golang修改结构体中的切片值方法

    golang修改结构体中的切片值,直接传结构体地址就可以 package main import "fmt" type rspInfo struct { KeyWords string `json:"key_words"` Value []string `json:"value"` } func setSlice(te *[]string){ str := "12" *te = append(*te,str) } //结构提传

  • golang切片扩容规则实现

    golang扩容规则 举个例子来演示下 package main import ( "fmt" ) func main() { arr1 := [4]int{1,2,3,4} //此时slice1为[1,2,3] 长度为3,容量为4 slice1 :=arr1[:3] fmt.Println(slice1,len(slice1),cap(slice1)) slice1 = append(slice1,5000,6000) fmt.Println(slice1,len(slice1),c

  • golang 切片的三种使用方式及区别的说明

    概念 切片(slice)是建立在数组之上的更方便,更灵活,更强大的数据结构.切片并不存储任何元素而只是对现有数组的引用. 三种方式及细节案例 ①定义一个切片,然后让切片去引用一个已经创建好的数组 package main import ( "fmt" ) func main() { var arr [5]int = [...]int {1, 2, 3, 4, 5} var slice = arr[1:3] fmt.Println("arr=", arr) fmt.P

  • Python开发技巧之海象运算符的三种运用方式

    目录 1. 第一个用法:if/else 2. 第二个用法:while 3. 第三个用法:推导式 Python 版本发展非常快,如今最新的版本已经是 Pyhton 3.9,即便如此,有很多人甚至还停留在 3.6 或者 3.7,连 3.8 还没用上. 很多 Python 3.8 的特性还没来得及了解,就已经成为旧知识了,比如今天要说的海象运算符. 海象运算符是在 PEP 572 被提出的,直到 3.8 版本合入发布. 它的英文原名叫 Assignment Expressions,翻译过来也就是 赋值

  • oracle中if/else的三种实现方式详解

    1.标准sql规范 1.单个IF IF v=... THEN END IF; 2.IF ... ELSE IF v=... THEN ELSE t....; END IF; 3.多个IF IF v=... THEN ELSIF v=... THEN t...; END IFL 注意: 多个IF的是'ELSIF' 不是 ' ELSE IF' 2.decode函数 DECODE(VALUE,IF1,THEN1,IF2,THEN2,IF2,THEN2,..,ELSE) 表示如果value等于if1时,

  • 详细解读分布式锁原理及三种实现方式

    目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题.分布式的CAP理论告诉我们"任何一个分布式系统都无法同时满足一致性(Consistency).可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项."所以,很多系统在设计之初就要对这三者做出取舍.在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证"最终一致性",只要这个最终

  • 浅谈js中的三种继承方式及其优缺点

    第一种,prototype的方式: //父类 function person(){ this.hair = 'black'; this.eye = 'black'; this.skin = 'yellow'; this.view = function(){ return this.hair + ',' + this.eye + ',' + this.skin; } } //子类 function man(){ this.feature = ['beard','strong']; } man.pr

  • IIS下PHP的三种配置方式对比

    在Windows IIS 6.0下配置PHP,通常有CGI.ISAPI和FastCGI三种配置方式,这三种模式都可以在IIS 6.0下成功运行,下面我就讲一下这三种方式配置的区别和性能上的差异.   1.CGI(通用网关接口/Common Gateway Interface)一般是可执行程序,例如EXE文件,和WEB服务器各自占据着不同的进程,而且一般一个CGI程序只能处理一个用户请求.这样,当用户请求数量非常多时,会大量占用系统的资源,如内存.CPU时间等,造成效能低下.   2.ISAPI(

  • Python selenium 三种等待方式详解(必会)

    很多人在群里问,这个下拉框定位不到.那个弹出框定位不到-各种定位不到,其实大多数情况下就是两种问题:1 有frame,2 没有加等待.殊不知,你的代码运行速度是什么量级的,而浏览器加载渲染速度又是什么量级的,就好比闪电侠和凹凸曼约好去打怪兽,然后闪电侠打完回来之后问凹凸曼你为啥还在穿鞋没出门?凹凸曼分分中内心一万只羊驼飞过,欺负哥速度慢,哥不跟你玩了,抛个异常撂挑子了. 那么怎么才能照顾到凹凸曼缓慢的加载速度呢?只有一个办法,那就是等喽.说到等,又有三种等法,且听博主一一道来: 1. 强制等待

  • Python编程入门之Hello World的三种实现方式

    本文实例讲述了Python编程入门之Hello World的三种实现方式.分享给大家供大家参考,具体如下: 第一种方式: $python >>>print('hello world') 屏幕上输出hello world print是一个常用函数 第二种方式: 复制代码 代码如下: $python hello.py 第三种方式: #!/usr/bin/env python chmod 755 hello.py ./hello.py 希望本文所述对大家Python程序设计有所帮助.

  • C++ 的三种访问权限与三种继承方式

    三种访问权限 我们知道C++中的类,有三种访问权限(也称作访问控制),它们分别是public.protected.private.要理解它们其实也很容易,看下面了一个例子. 父类: class Person { public: Person(const string& name, int age) : m_name(name), m_age(age) { } void ShowInfo() { cout << "姓名:" << m_name <&l

  • 浅谈js函数三种定义方式 & 四种调用方式 & 调用顺序

    在Javascript定义一个函数一般有如下三种方式: 函数关键字(function)语句: function fnMethodName(x){alert(x);} 函数字面量(Function Literals): var fnMethodName = function(x){alert(x);} Function()构造函数: var fnMethodName = new Function('x','alert(x);') // 由Function构造函数的参数个数可变.最后一个参数写函数体

随机推荐