5.Go语言数组和切片(二)

2019-05-29  本文已影响0人  一枼落知天下

main.go

// Go语言数组和切片
package main

//  包的本质是创建不同的文件夹
//  go的每一个文件都是属于一个包的
//  go以包的形式管理项目和文件目录。
//  import "包的路径"
import (
     "day7/model/utils" 
    _"fmt"
)


var content string = `
————————————————Go语言数组和切片————————————————————
一、数组
二、切片

`


/**
 * [init init函数初始化工作。main函数之前执行]
 * @author Jhou Shuai
 * @datetime 2019-05-20T22:49:36+0800
 */
// func init() {
//  fmt.Println(content)
// }


func main() {
    utils.Entry()
}

utils.go

// Go语言数组和切片
package utils

import (
    "fmt"
    "strings"
)

var layout string = "2006-01-02"

// 全局变量
var Author string = "Jhou Shuai"

// 全局变量
var Description string = "Go语言数组和切片"

//全局变量:使用反引号来定义多行字符串
var Content string = `
————————————————Go语言数组和切片————————————————————
一、数组
    1)数组是值类型:
    2)数组可以存放多个同一类型的数据
    3)增加程序可维护性
    4)代码更加清晰,易扩展
二、切片
    1.切片的长度是可以变化的,是一个动态变化数组
    切片的容量是可以动态变化的
    var 切片名 []类型
    var intSlice []int 
    第一种: mySlice := intArr[1:3]
    2.切片在内存中的表现形式
    3.切片引用类型:在传递时候,遵守引用传递机制
    4.数据结构:struct结构体
        type slicestuct{
            ptr *[2]int
            len int
            cap int
        }
    5.第二种:make 创建切片
        类型,长度,容量
        cap>=len
        var 切片名 []type = make([]type,len,[cap])
        var slice []float64 = make([]float64, 5,10)

    6.第三种:定义一个切片,直接就指定具体的数组
    var strSlice []string = []string{"Faker","Uzi","Mata"}
`

/**
 * [Init 入口]
 * @author Jhou Shuai
 * @datetime 2019-05-18T11:58:33+0800
 */
func Entry() {
    [1 1 2 3 5 8 13 21 34 55]
    fmt.Println(fbn(10))
}


func sliceInit() {
    // 第一种方式:
    // var intArr [5]int = [...]int{1,22,33,44,55}
    // // 切片操作:
    // // 1.
    // // 引用intArr数组的起始下标为1,最后的下标为3(不包含3)
    // mySlice := intArr[1:3]
    // fmt.Println("intArr= ",intArr)
    // fmt.Println("mySlice中的元素:",mySlice)
    // fmt.Println("mySlice中的长度:",len(mySlice))
    // // 切片的容量是可以动态变化的
    // fmt.Println("mySlice中的容量:",cap(mySlice))

    // fmt.Println()
    // // 数组的各个元素的地址间隔是依据数组的类型决定的,
    // //      比如:int64->8个字节、int32->4个字节 int16 ->2个字节 、int->8个字节
    // fmt.Printf("intArr地址%p \n",&intArr)
    // for i := 0; i <len(intArr); i++ {
    //     fmt.Printf("intArr[%v]的地址%p \n",i,&intArr[i])
    // }

    // fmt.Println()
    // fmt.Printf("mySlice地址%p \n",&mySlice)
    // for i := 0; i <len(mySlice); i++ {
    //     fmt.Printf("mySlice[%v]的地址%p \n",i,&mySlice[i])
    // }

    // mySlice[1] = 66
    // fmt.Println("intArr= ",intArr)
    // fmt.Println("mySlice中的元素:",mySlice)

    // 第二种方式:
    fmt.Println()
    var slice []float64 = make([]float64, 5,10)
    // 对于切片必须,make才能使用 
    // [0 0 0 0 0] 默认全部为零
    slice[1] = 64
    slice[3] = 100
    fmt.Printf("元素:%v,长度:%v,容量:%v \n",slice,len(slice),cap(slice))
    for i := 0; i <len(slice); i++ {
        fmt.Printf("slice[%v]的地址%p \n",i,&slice[i])
    }
    // 元素:[0 64 0 100 0],长度:5,容量:10
    // slice[0]的地址0xc0000700f0
    // slice[1]的地址0xc0000700f8    0xc0000700f8  = 0xc0000700f0 + 8
    // slice[2]的地址0xc000070100    0xc000070100  = 0xc0000700f8 + 8
    // slice[3]的地址0xc000070108    0xc000070108  = 0xc000070100 + 8
    // slice[4]的地址0xc000070110    0xc000070110  = 0xc000070108 + 8

    // 通过make方式创建切片可以指定切片的大小和容量
    // 如果没有给切片的各个元素赋值,那么就会使用默认值
    //      int float => 0
    //      string => ""
    //      bool => false
    //  通过make方式创建的切片对应的数组是由make底层维护,对外
    //  不可见,即只能通过slice去访问各个元素。
    //  
    // 第三种方式:
    fmt.Println()
    var strSlice []string = []string{"Faker","Uzi","Mata"}
    fmt.Printf("元素:%v,长度:%v,容量:%v \n",strSlice,len(strSlice),cap(strSlice))
    for i := 0; i <len(strSlice); i++ {
        fmt.Printf("strSlice[%v]的地址%p \n",i,&strSlice[i])
    }
    // 元素:[Faker Uzi Mata],长度:3,容量:3
    // strSlice[0]的地址0xc000080300
    // strSlice[1]的地址0xc000080310   0xc000080310 = 0xc000080300 + 16
    // strSlice[2]的地址0xc000080320   0xc000080320 = 0xc000080310 + 16
    // 
    // 
    //  第一种方式和第二种方式的区别:
    //  第一种方式:
    //      直接引用数组,这个数组是事先存在的,是可见的
    //  第二种方式:
    //      通过make来创建切片,make也会创建一个数组,是由切片在
    //   底层维护,是不可见的
}


func sliceForRange() {
    var intArr [5]int = [...]int{10,20,30,40,50}

    intSlice := intArr[0:]

    for i := 0; i <len(intSlice); i++ {
        fmt.Printf("intSlice[%v] = %v \n",i,intSlice[i])
    }

    fmt.Println()
    for key,value := range intSlice {
         fmt.Printf("intSlice[%v] = %v \n",key,value)
    }

    fmt.Println()
    for _,value := range intSlice {
         fmt.Printf( "%v \t",value)
    }
}

/**
 * [sliceUseDetail 切片注意事项和细节说明]
 * @author Jhou Shuai
 * @datetime 2019-05-29T20:41:33+0800
 */
func sliceUseDetail() {
    // 不要越界
    // var slice = arr[startIndex,endIndex]
    // 从arr数组下标startIndex,取到下标为endIndex的元素(不含arr[endIndex])
    // var slice = arr[:len(arr)]
    // var slice = arr[start:]
    // var slice = arr[:end]
    // var slice = arr[:]
    // 
    // cap 容量
    // 可以多次切片,切了在切,
    // 
    // append 内置函数 
    // 可以对切片进行动态追加
    var intSlice []int = []int{100,200,300}
    fmt.Println(intSlice)
    for i := 0; i <len(intSlice); i++ {
        fmt.Printf("intSlice[%v]的地址%p \n",i,&intSlice[i])
    }
    // 通过append直接给intSlice追加元素
    intSlice0 := append(intSlice,400,500)


    fmt.Println(intSlice0)
    for i := 0; i <len(intSlice0); i++ {
        fmt.Printf("intSlice0[%v]的地址%p \n",i,&intSlice0[i])
    }
    // 通过append将切片intSlice追加给intSlice
    intSlice = append(intSlice,intSlice...)
    fmt.Println(intSlice)
    // 切片append操作的本质是对数组扩容
    // 不是针对原来的数组,而是
    // go底层会创建一个新的数组newArr(按照扩容后大小)
    // 刚创建所有默认值为零;然后
    // 将intSlice原来包含的元素拷贝到新的数组newArr
    // 切片intSlice重新应用新数组newArr
    // 新的数组newArr是在底层维护,不可见的
    // 原来的数组就会被回收。
    
    // 切片的拷贝 copy 两个参数的数据类型:切片
    // 两个切片的数据空间是独立。相互不影响
    // 切片类型才可以执行copy
    fmt.Println()
    var slice4 []int = []int{1,2,3,4,5};
    var slice5 = make([]int, 10)
    copy(slice5,slice4)
    fmt.Println(slice4)
    for i := 0; i <len(slice4); i++ {
        fmt.Printf("slice4[%v]的地址%p \n",i,&slice4[i])
    }
    //     [1 2 3 4 5]
    // slice4[0]的地址0xc000094090
    // slice4[1]的地址0xc000094098
    // slice4[2]的地址0xc0000940a0
    // slice4[3]的地址0xc0000940a8
    // slice4[4]的地址0xc0000940b0

    fmt.Println(slice5)
    for i := 0; i <len(slice5); i++ {
        fmt.Printf("slice5[%v]的地址%p \n",i,&slice5[i])
    }
    //      [1 2 3 4 5 0 0 0 0 0]
    // slice5[0]的地址0xc0000700f0
    // slice5[1]的地址0xc0000700f8
    // slice5[2]的地址0xc000070100
    // slice5[3]的地址0xc000070108
    // slice5[4]的地址0xc000070110
    // slice5[5]的地址0xc000070118
    // slice5[6]的地址0xc000070120
    // slice5[7]的地址0xc000070128
    // slice5[8]的地址0xc000070130
    // slice5[9]的地址0xc000070138

    // slice5,slice4是两个相互独立的空间
    // 
    
    // 不会报错,只会拷贝一个
    var slice6 = make([]int, 1)
    copy(slice6,slice4)
    // [1]
    fmt.Println(slice6)
}


/**
 * [stringSlice 字符串、切片]
 * @author Jhou Shuai
 * @datetime 2019-05-29T22:15:32+0800
 */
func stringSlice() {
    // string底层是一个byte数组,因此也可以进行切片处理
    // string和切片在内存的形式:
    var name string = "ZhouShuai@163.com"

    var strSlice =name[strings.Index(name,"@"):]

    fmt.Println(strSlice)

    // string是不可变的,也就是不能通过str[0]='z'方式来修改字符串
    // 
    // 
    // 如果需要修改字符串,可以将string-》[]byte 或[]rune->修改-》重写转成string
    arrSlice := []byte(name)
    arrSlice[0]='J'
    var arrStr = string(arrSlice)
    // JhouShuai@163.com
    fmt.Println(arrStr)
    // []byte
    // 转成[]byte后,可以处理英文和数字,不能处理中文
    // 原因是[]byte字节来处理,而一个汉字,是三个字节,因此会出现乱码
    // 
    // []rune
    // 解决方法是:将string 转成[]rune 即可,因为[]rune是按字符处理的
    // 可以兼容汉字

    arrSlice1 := []rune(name)
    arrSlice1[0]='周'
    var arrStr1 = string(arrSlice1)
    // 周houShuai@163.com
    fmt.Println(arrStr1)
}

/**
 * [fbn 斐波拉契数列]
 * @author Jhou Shuai
 * @datetime 2019-05-29T22:59:40+0800
 * [1 1 2 3 5 8 13 21 34 55]
 * fmt.Println(fbn(10))
 */
func fbn(n int) ([]uint64) {
    /**
     * 思路:
     * 1.声明一个函数,fbn(n int) ([]uint64){}
     */
     var fbnSlice = make([]uint64, n)
     fbnSlice[0] = 1
     fbnSlice[1] = 1
     for i := 2; i <n; i++ {
        fbnSlice[i] = fbnSlice[i-1] + fbnSlice[i-2]
     }
     return fbnSlice
}
上一篇 下一篇

猜你喜欢

热点阅读